3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -1517,6 +1517,9 @@ def HLSLMixPackOffset : DiagGroup<"mix-packoffset">;
// Warnings for DXIL validation
def DXILValidation : DiagGroup<"dxil-validation">;

// Warning for HLSL API availability
def HLSLAvailability : DiagGroup<"hlsl-availability">;

// Warnings and notes related to const_var_decl_type attribute checks
def ReadOnlyPlacementChecks : DiagGroup<"read-only-types">;

Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -12239,6 +12239,13 @@ def err_hlsl_param_qualifier_mismatch :
def warn_hlsl_impcast_vector_truncation : Warning<
"implicit conversion truncates vector: %0 to %1">, InGroup<Conversion>;

def warn_hlsl_availability : Warning<
"%0 is only available %select{|in %4 environment }3on %1 %2 or newer">,
InGroup<HLSLAvailability>, DefaultError;
def warn_hlsl_availability_unavailable :
Warning<err_unavailable.Summary>,
InGroup<HLSLAvailability>, DefaultError;

// Layout randomization diagnostics.
def err_non_designated_init_used : Error<
"a randomized struct can only be initialized with a designated initializer">;
Expand Down
6 changes: 2 additions & 4 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -5465,10 +5465,6 @@ def pg : Flag<["-"], "pg">, HelpText<"Enable mcount instrumentation">,
MarshallingInfoFlag<CodeGenOpts<"InstrumentForProfiling">>;
def pipe : Flag<["-", "--"], "pipe">,
HelpText<"Use pipes between commands, when possible">;
// Facebook T92898286
def post_link_optimize : Flag<["--"], "post-link-optimize">,
HelpText<"Apply post-link optimizations using BOLT">;
// End Facebook T92898286
def prebind__all__twolevel__modules : Flag<["-"], "prebind_all_twolevel_modules">;
def prebind : Flag<["-"], "prebind">;
def preload : Flag<["-"], "preload">;
Expand Down Expand Up @@ -6288,6 +6284,8 @@ def mno_apx_features_EQ : CommaJoined<["-"], "mno-apx-features=">, Group<m_x86_F
// For stability, we only add a feature to -mapxf after it passes the validation of llvm-test-suite && cpu2017 on Intel SDE.
def mapxf : Flag<["-"], "mapxf">, Alias<mapx_features_EQ>, AliasArgs<["egpr","push2pop2","ppx","ndd","ccmp","nf"]>;
def mno_apxf : Flag<["-"], "mno-apxf">, Alias<mno_apx_features_EQ>, AliasArgs<["egpr","push2pop2","ppx","ndd","ccmp","nf"]>;
def mapx_inline_asm_use_gpr32 : Flag<["-"], "mapx-inline-asm-use-gpr32">, Group<m_Group>,
HelpText<"Enable use of GPR32 in inline assembly for APX">;
} // let Flags = [TargetSpecific]

// VE feature flags
Expand Down
36 changes: 36 additions & 0 deletions clang/include/clang/Sema/Attr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===----- Attr.h --- Helper functions for attribute handling in Sema -----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file provides helpers for Sema functions that handle attributes.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_ATTR_H
#define LLVM_CLANG_SEMA_ATTR_H

#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "llvm/Support/Casting.h"

namespace clang {

/// isFuncOrMethodForAttrSubject - Return true if the given decl has function
/// type (function or function-typed variable) or an Objective-C
/// method.
inline bool isFuncOrMethodForAttrSubject(const Decl *D) {
return (D->getFunctionType() != nullptr) || llvm::isa<ObjCMethodDecl>(D);
}

/// Return true if the given decl has function type (function or
/// function-typed variable) or an Objective-C method or a block.
inline bool isFunctionOrMethodOrBlockForAttrSubject(const Decl *D) {
return isFuncOrMethodForAttrSubject(D) || llvm::isa<BlockDecl>(D);
}

} // namespace clang
#endif // LLVM_CLANG_SEMA_ATTR_H
218 changes: 120 additions & 98 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/TinyPtrVector.h"
#include <deque>
#include <memory>
Expand Down Expand Up @@ -168,15 +169,25 @@ class Preprocessor;
class PseudoDestructorTypeStorage;
class PseudoObjectExpr;
class QualType;
class SemaAMDGPU;
class SemaARM;
class SemaBPF;
class SemaCodeCompletion;
class SemaCUDA;
class SemaHLSL;
class SemaHexagon;
class SemaLoongArch;
class SemaMIPS;
class SemaNVPTX;
class SemaObjC;
class SemaOpenACC;
class SemaOpenMP;
class SemaPPC;
class SemaPseudoObject;
class SemaRISCV;
class SemaSYCL;
class SemaSystemZ;
class SemaWasm;
class SemaX86;
class StandardConversionSequence;
class Stmt;
Expand Down Expand Up @@ -884,9 +895,6 @@ class Sema final : public SemaBase {
void disable() { Active = false; }
};

/// Build a partial diagnostic.
PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h

sema::FunctionScopeInfo *getCurFunction() const {
return FunctionScopes.empty() ? nullptr : FunctionScopes.back();
}
Expand Down Expand Up @@ -993,6 +1001,21 @@ class Sema final : public SemaBase {
/// CurContext - This is the current declaration context of parsing.
DeclContext *CurContext;

SemaAMDGPU &AMDGPU() {
assert(AMDGPUPtr);
return *AMDGPUPtr;
}

SemaARM &ARM() {
assert(ARMPtr);
return *ARMPtr;
}

SemaBPF &BPF() {
assert(BPFPtr);
return *BPFPtr;
}

SemaCodeCompletion &CodeCompletion() {
assert(CodeCompletionPtr);
return *CodeCompletionPtr;
Expand All @@ -1008,6 +1031,26 @@ class Sema final : public SemaBase {
return *HLSLPtr;
}

SemaHexagon &Hexagon() {
assert(HexagonPtr);
return *HexagonPtr;
}

SemaLoongArch &LoongArch() {
assert(LoongArchPtr);
return *LoongArchPtr;
}

SemaMIPS &MIPS() {
assert(MIPSPtr);
return *MIPSPtr;
}

SemaNVPTX &NVPTX() {
assert(NVPTXPtr);
return *NVPTXPtr;
}

SemaObjC &ObjC() {
assert(ObjCPtr);
return *ObjCPtr;
Expand All @@ -1023,6 +1066,11 @@ class Sema final : public SemaBase {
return *OpenMPPtr;
}

SemaPPC &PPC() {
assert(PPCPtr);
return *PPCPtr;
}

SemaPseudoObject &PseudoObject() {
assert(PseudoObjectPtr);
return *PseudoObjectPtr;
Expand All @@ -1038,6 +1086,16 @@ class Sema final : public SemaBase {
return *SYCLPtr;
}

SemaSystemZ &SystemZ() {
assert(SystemZPtr);
return *SystemZPtr;
}

SemaWasm &Wasm() {
assert(WasmPtr);
return *WasmPtr;
}

SemaX86 &X86() {
assert(X86Ptr);
return *X86Ptr;
Expand Down Expand Up @@ -1073,15 +1131,25 @@ class Sema final : public SemaBase {

mutable IdentifierInfo *Ident_super;

std::unique_ptr<SemaAMDGPU> AMDGPUPtr;
std::unique_ptr<SemaARM> ARMPtr;
std::unique_ptr<SemaBPF> BPFPtr;
std::unique_ptr<SemaCodeCompletion> CodeCompletionPtr;
std::unique_ptr<SemaCUDA> CUDAPtr;
std::unique_ptr<SemaHLSL> HLSLPtr;
std::unique_ptr<SemaHexagon> HexagonPtr;
std::unique_ptr<SemaLoongArch> LoongArchPtr;
std::unique_ptr<SemaMIPS> MIPSPtr;
std::unique_ptr<SemaNVPTX> NVPTXPtr;
std::unique_ptr<SemaObjC> ObjCPtr;
std::unique_ptr<SemaOpenACC> OpenACCPtr;
std::unique_ptr<SemaOpenMP> OpenMPPtr;
std::unique_ptr<SemaPPC> PPCPtr;
std::unique_ptr<SemaPseudoObject> PseudoObjectPtr;
std::unique_ptr<SemaRISCV> RISCVPtr;
std::unique_ptr<SemaSYCL> SYCLPtr;
std::unique_ptr<SemaSystemZ> SystemZPtr;
std::unique_ptr<SemaWasm> WasmPtr;
std::unique_ptr<SemaX86> X86Ptr;

///@}
Expand Down Expand Up @@ -2074,6 +2142,8 @@ class Sema final : public SemaBase {
unsigned MaxArgCount);
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount);

bool ValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);

private:
void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
const ArraySubscriptExpr *ASE = nullptr,
Expand All @@ -2087,8 +2157,6 @@ class Sema final : public SemaBase {
ArrayRef<const Expr *> Args,
const FunctionProtoType *Proto, SourceLocation Loc);

void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg);

void CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl,
StringRef ParamName, QualType ArgTy, QualType ParamTy);

Expand All @@ -2102,54 +2170,13 @@ class Sema final : public SemaBase {

void checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, CallExpr *TheCall);

bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
unsigned MaxWidth);
bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool ParseSVEImmChecks(CallExpr *TheCall,
SmallVector<std::tuple<int, int, int>, 3> &ImmChecks);
bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg,
bool WantCDE);
bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);

bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
bool CheckBPFBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
bool CheckMipsBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
bool CheckMipsBuiltinCpu(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
bool CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
bool CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);

bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI,
unsigned BuiltinID, CallExpr *TheCall);
bool CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI,
unsigned BuiltinID,
CallExpr *TheCall);
bool CheckNVPTXBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);

bool BuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall);
bool BuiltinVAStartARMMicrosoft(CallExpr *Call);
bool BuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID);
bool BuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
unsigned BuiltinID);
bool BuiltinComplex(CallExpr *TheCall);
bool BuiltinVSX(CallExpr *TheCall);
bool BuiltinOSLogFormat(CallExpr *TheCall);
bool ValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);

bool BuiltinPrefetch(CallExpr *TheCall);
bool BuiltinAllocaWithAlign(CallExpr *TheCall);
Expand All @@ -2162,13 +2189,6 @@ class Sema final : public SemaBase {
ExprResult BuiltinNontemporalOverloaded(ExprResult TheCallResult);
ExprResult AtomicOpsOverloaded(ExprResult TheCallResult,
AtomicExpr::AtomicOp Op);
bool BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, int ArgNum,
unsigned ExpectedFieldNum, bool AllowName);
bool BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall);
bool BuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID,
const char *TypeDesc);

bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc);

bool BuiltinElementwiseMath(CallExpr *TheCall);
bool BuiltinElementwiseTernaryMath(CallExpr *TheCall,
Expand All @@ -2185,16 +2205,6 @@ class Sema final : public SemaBase {
ExprResult BuiltinMatrixColumnMajorStore(CallExpr *TheCall,
ExprResult CallResult);

// WebAssembly builtin handling.
bool BuiltinWasmRefNullExtern(CallExpr *TheCall);
bool BuiltinWasmRefNullFunc(CallExpr *TheCall);
bool BuiltinWasmTableGet(CallExpr *TheCall);
bool BuiltinWasmTableSet(CallExpr *TheCall);
bool BuiltinWasmTableSize(CallExpr *TheCall);
bool BuiltinWasmTableGrow(CallExpr *TheCall);
bool BuiltinWasmTableFill(CallExpr *TheCall);
bool BuiltinWasmTableCopy(CallExpr *TheCall);

bool CheckFormatArguments(const FormatAttr *Format,
ArrayRef<const Expr *> Args, bool IsCXXMember,
VariadicCallType CallType, SourceLocation Loc,
Expand Down Expand Up @@ -3548,6 +3558,53 @@ class Sema final : public SemaBase {
BuiltinFunction
};

/// A helper function to provide Attribute Location for the Attr types
/// AND the ParsedAttr.
template <typename AttrInfo>
static std::enable_if_t<std::is_base_of_v<Attr, AttrInfo>, SourceLocation>
getAttrLoc(const AttrInfo &AL) {
return AL.getLocation();
}
SourceLocation getAttrLoc(const ParsedAttr &AL);

/// If Expr is a valid integer constant, get the value of the integer
/// expression and return success or failure. May output an error.
///
/// Negative argument is implicitly converted to unsigned, unless
/// \p StrictlyUnsigned is true.
template <typename AttrInfo>
bool checkUInt32Argument(const AttrInfo &AI, const Expr *Expr, uint32_t &Val,
unsigned Idx = UINT_MAX,
bool StrictlyUnsigned = false) {
std::optional<llvm::APSInt> I = llvm::APSInt(32);
if (Expr->isTypeDependent() ||
!(I = Expr->getIntegerConstantExpr(Context))) {
if (Idx != UINT_MAX)
Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
<< &AI << Idx << AANT_ArgumentIntegerConstant
<< Expr->getSourceRange();
else
Diag(getAttrLoc(AI), diag::err_attribute_argument_type)
<< &AI << AANT_ArgumentIntegerConstant << Expr->getSourceRange();
return false;
}

if (!I->isIntN(32)) {
Diag(Expr->getExprLoc(), diag::err_ice_too_large)
<< toString(*I, 10, false) << 32 << /* Unsigned */ 1;
return false;
}

if (StrictlyUnsigned && I->isSigned() && I->isNegative()) {
Diag(getAttrLoc(AI), diag::err_attribute_requires_positive_integer)
<< &AI << /*non-negative*/ 1;
return false;
}

Val = (uint32_t)I->getZExtValue();
return true;
}

/// WeakTopLevelDecl - Translation-unit scoped declarations generated by
/// \#pragma weak during processing of other Decls.
/// I couldn't figure out a clean way to generate these in-line, so
Expand Down Expand Up @@ -3705,41 +3762,6 @@ class Sema final : public SemaBase {

BTFDeclTagAttr *mergeBTFDeclTagAttr(Decl *D, const BTFDeclTagAttr &AL);

WebAssemblyImportNameAttr *
mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL);
WebAssemblyImportModuleAttr *
mergeImportModuleAttr(Decl *D, const WebAssemblyImportModuleAttr &AL);

/// Create an AMDGPUWavesPerEUAttr attribute.
AMDGPUFlatWorkGroupSizeAttr *
CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min,
Expr *Max);

/// addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size
/// attribute to a particular declaration.
void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *Min, Expr *Max);

/// Create an AMDGPUWavesPerEUAttr attribute.
AMDGPUWavesPerEUAttr *
CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min,
Expr *Max);

/// addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a
/// particular declaration.
void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *Min, Expr *Max);

/// Create an AMDGPUMaxNumWorkGroupsAttr attribute.
AMDGPUMaxNumWorkGroupsAttr *
CreateAMDGPUMaxNumWorkGroupsAttr(const AttributeCommonInfo &CI, Expr *XExpr,
Expr *YExpr, Expr *ZExpr);

/// addAMDGPUMaxNumWorkGroupsAttr - Adds an amdgpu_max_num_work_groups
/// attribute to a particular declaration.
void addAMDGPUMaxNumWorkGroupsAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *XExpr, Expr *YExpr, Expr *ZExpr);

DLLImportAttr *mergeDLLImportAttr(Decl *D, const AttributeCommonInfo &CI);
DLLExportAttr *mergeDLLExportAttr(Decl *D, const AttributeCommonInfo &CI);
MSInheritanceAttr *mergeMSInheritanceAttr(Decl *D,
Expand Down
68 changes: 68 additions & 0 deletions clang/include/clang/Sema/SemaAMDGPU.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===----- SemaAMDGPU.h --- AMDGPU target-specific routines ---*- 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to AMDGPU.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMAAMDGPU_H
#define LLVM_CLANG_SEMA_SEMAAMDGPU_H

#include "clang/AST/Attr.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/AttributeCommonInfo.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class SemaAMDGPU : public SemaBase {
public:
SemaAMDGPU(Sema &S);

bool CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);

/// Create an AMDGPUWavesPerEUAttr attribute.
AMDGPUFlatWorkGroupSizeAttr *
CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min,
Expr *Max);

/// addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size
/// attribute to a particular declaration.
void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *Min, Expr *Max);

/// Create an AMDGPUWavesPerEUAttr attribute.
AMDGPUWavesPerEUAttr *
CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min,
Expr *Max);

/// addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a
/// particular declaration.
void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *Min, Expr *Max);

/// Create an AMDGPUMaxNumWorkGroupsAttr attribute.
AMDGPUMaxNumWorkGroupsAttr *
CreateAMDGPUMaxNumWorkGroupsAttr(const AttributeCommonInfo &CI, Expr *XExpr,
Expr *YExpr, Expr *ZExpr);

/// addAMDGPUMaxNumWorkGroupsAttr - Adds an amdgpu_max_num_work_groups
/// attribute to a particular declaration.
void addAMDGPUMaxNumWorkGroupsAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *XExpr, Expr *YExpr, Expr *ZExpr);

void handleAMDGPUWavesPerEUAttr(Decl *D, const ParsedAttr &AL);
void handleAMDGPUNumSGPRAttr(Decl *D, const ParsedAttr &AL);
void handleAMDGPUNumVGPRAttr(Decl *D, const ParsedAttr &AL);
void handleAMDGPUMaxNumWorkGroupsAttr(Decl *D, const ParsedAttr &AL);
void handleAMDGPUFlatWorkGroupSizeAttr(Decl *D, const ParsedAttr &AL);
};
} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMAAMDGPU_H
63 changes: 63 additions & 0 deletions clang/include/clang/Sema/SemaARM.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//===----- SemaARM.h ------- ARM target-specific routines -----*- 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to ARM.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMAARM_H
#define LLVM_CLANG_SEMA_SEMAARM_H

#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaBase.h"
#include "llvm/ADT/SmallVector.h"
#include <tuple>

namespace clang {

class SemaARM : public SemaBase {
public:
SemaARM(Sema &S);

enum ArmStreamingType {
ArmNonStreaming,
ArmStreaming,
ArmStreamingCompatible,
ArmStreamingOrSVE2p1
};

bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
unsigned MaxWidth);
bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool
ParseSVEImmChecks(CallExpr *TheCall,
llvm::SmallVector<std::tuple<int, int, int>, 3> &ImmChecks);
bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg,
bool WantCDE);
bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);

bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
bool BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, int ArgNum,
unsigned ExpectedFieldNum, bool AllowName);
bool BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall);
};

SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD);

} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMAARM_H
28 changes: 28 additions & 0 deletions clang/include/clang/Sema/SemaBPF.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===----- SemaBPF.h ------- BPF target-specific routines -----*- 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to BPF.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMABPF_H
#define LLVM_CLANG_SEMA_SEMABPF_H

#include "clang/AST/Expr.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class SemaBPF : public SemaBase {
public:
SemaBPF(Sema &S);

bool CheckBPFBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
};
} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMABPF_H
3 changes: 3 additions & 0 deletions clang/include/clang/Sema/SemaBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ class SemaBase {
/// Emit a partial diagnostic.
SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD,
bool DeferHint = false);

/// Build a partial diagnostic.
PartialDiagnostic PDiag(unsigned DiagID = 0);
};

} // namespace clang
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Sema/SemaHLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class SemaHLSL : public SemaBase {
void DiagnoseAttrStageMismatch(
const Attr *A, HLSLShaderAttr::ShaderType Stage,
std::initializer_list<HLSLShaderAttr::ShaderType> AllowedStages);
void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU);
};

} // namespace clang
Expand Down
29 changes: 29 additions & 0 deletions clang/include/clang/Sema/SemaHexagon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===----- SemaHexagon.h -- Hexagon target-specific routines --*- 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to Hexagon.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMAHEXAGON_H
#define LLVM_CLANG_SEMA_SEMAHEXAGON_H

#include "clang/AST/Expr.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class SemaHexagon : public SemaBase {
public:
SemaHexagon(Sema &S);

bool CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
};
} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMAHEXAGON_H
4 changes: 0 additions & 4 deletions clang/include/clang/Sema/SemaInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@

namespace clang {

inline PartialDiagnostic Sema::PDiag(unsigned DiagID) {
return PartialDiagnostic(DiagID, Context.getDiagAllocator());
}

inline bool
FTIHasSingleVoidParameter(const DeclaratorChunk::FunctionTypeInfo &FTI) {
return FTI.NumParams == 1 && !FTI.isVariadic &&
Expand Down
30 changes: 30 additions & 0 deletions clang/include/clang/Sema/SemaLoongArch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===-- SemaLoongArch.h -- LoongArch target-specific routines --*- 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to LoongArch.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMALOONGARCH_H
#define LLVM_CLANG_SEMA_SEMALOONGARCH_H

#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class SemaLoongArch : public SemaBase {
public:
SemaLoongArch(Sema &S);

bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI,
unsigned BuiltinID, CallExpr *TheCall);
};
} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMALOONGARCH_H
33 changes: 33 additions & 0 deletions clang/include/clang/Sema/SemaMIPS.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===----- SemaMIPS.h ------ MIPS target-specific routines ----*- 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to MIPS.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMAMIPS_H
#define LLVM_CLANG_SEMA_SEMAMIPS_H

#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class SemaMIPS : public SemaBase {
public:
SemaMIPS(Sema &S);

bool CheckMipsBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
bool CheckMipsBuiltinCpu(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
bool CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
};
} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMAMIPS_H
30 changes: 30 additions & 0 deletions clang/include/clang/Sema/SemaNVPTX.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===----- SemaNVPTX.h ----- NVPTX target-specific routines ---*- 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to NVPTX.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMANVPTX_H
#define LLVM_CLANG_SEMA_SEMANVPTX_H

#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class SemaNVPTX : public SemaBase {
public:
SemaNVPTX(Sema &S);

bool CheckNVPTXBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
};
} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMANVPTX_H
58 changes: 58 additions & 0 deletions clang/include/clang/Sema/SemaPPC.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//===----- SemaPPC.h ------- PPC target-specific routines -----*- 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to PowerPC.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMAPPC_H
#define LLVM_CLANG_SEMA_SEMAPPC_H

#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class SemaPPC : public SemaBase {
public:
SemaPPC(Sema &S);

bool CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
// 16 byte ByVal alignment not due to a vector member is not honoured by XL
// on AIX. Emit a warning here that users are generating binary incompatible
// code to be safe.
// Here we try to get information about the alignment of the struct member
// from the struct passed to the caller function. We only warn when the struct
// is passed byval, hence the series of checks and early returns if we are a
// not passing a struct byval.
void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg);

/// BuiltinPPCMMACall - Check the call to a PPC MMA builtin for validity.
/// Emit an error and return true on failure; return false on success.
/// TypeStr is a string containing the type descriptor of the value returned
/// by the builtin and the descriptors of the expected type of the arguments.
bool BuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID,
const char *TypeDesc);

bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc);

// Customized Sema Checking for VSX builtins that have the following
// signature: vector [...] builtinName(vector [...], vector [...], const int);
// Which takes the same type of vectors (any legal vector type) for the first
// two arguments and takes compile time constant for the third argument.
// Example builtins are :
// vector double vec_xxpermdi(vector double, vector double, int);
// vector short vec_xxsldwi(vector short, vector short, int);
bool BuiltinVSX(CallExpr *TheCall);
};
} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMAPPC_H
28 changes: 28 additions & 0 deletions clang/include/clang/Sema/SemaSystemZ.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===----- SemaSystemZ.h -- SystemZ target-specific routines --*- 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to SystemZ.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMASYSTEMZ_H
#define LLVM_CLANG_SEMA_SEMASYSTEMZ_H

#include "clang/AST/Expr.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class SemaSystemZ : public SemaBase {
public:
SemaSystemZ(Sema &S);

bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
};
} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMASYSTEMZ_H
52 changes: 52 additions & 0 deletions clang/include/clang/Sema/SemaWasm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//===----- SemaWasm.h ------ Wasm target-specific routines ----*- 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis functions specific to Wasm.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMAWASM_H
#define LLVM_CLANG_SEMA_SEMAWASM_H

#include "clang/AST/Attr.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class SemaWasm : public SemaBase {
public:
SemaWasm(Sema &S);

bool CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI,
unsigned BuiltinID,
CallExpr *TheCall);

bool BuiltinWasmRefNullExtern(CallExpr *TheCall);
bool BuiltinWasmRefNullFunc(CallExpr *TheCall);
bool BuiltinWasmTableGet(CallExpr *TheCall);
bool BuiltinWasmTableSet(CallExpr *TheCall);
bool BuiltinWasmTableSize(CallExpr *TheCall);
bool BuiltinWasmTableGrow(CallExpr *TheCall);
bool BuiltinWasmTableFill(CallExpr *TheCall);
bool BuiltinWasmTableCopy(CallExpr *TheCall);

WebAssemblyImportNameAttr *
mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL);
WebAssemblyImportModuleAttr *
mergeImportModuleAttr(Decl *D, const WebAssemblyImportModuleAttr &AL);

void handleWebAssemblyExportNameAttr(Decl *D, const ParsedAttr &AL);
void handleWebAssemblyImportModuleAttr(Decl *D, const ParsedAttr &AL);
void handleWebAssemblyImportNameAttr(Decl *D, const ParsedAttr &AL);
};
} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMAWASM_H
2 changes: 1 addition & 1 deletion clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6794,7 +6794,7 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const {
// Using shadow declarations with the same target match.
if (const auto *USX = dyn_cast<UsingShadowDecl>(X)) {
const auto *USY = cast<UsingShadowDecl>(Y);
return USX->getTargetDecl() == USY->getTargetDecl();
return declaresSameEntity(USX->getTargetDecl(), USY->getTargetDecl());
}

// Using declarations with the same qualifier match. (We already know that
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2408,9 +2408,11 @@ Expr *VarDecl::getInit() {
return cast<Expr>(S);

auto *Eval = getEvaluatedStmt();
return cast<Expr>(Eval->Value.isOffset()
? Eval->Value.get(getASTContext().getExternalSource())
: Eval->Value.get(nullptr));

return cast_if_present<Expr>(
Eval->Value.isOffset()
? Eval->Value.get(getASTContext().getExternalSource())
: Eval->Value.get(nullptr));
}

Stmt **VarDecl::getInitAddress() {
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,8 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
IdentifierInfo *IIEnv = A->getEnvironment();
StringRef TargetEnv =
Context.getTargetInfo().getTriple().getEnvironmentName();
StringRef EnvName = AvailabilityAttr::getPrettyEnviromentName(TargetEnv);
StringRef EnvName = AvailabilityAttr::getPrettyEnviromentName(
Context.getTargetInfo().getTriple().getEnvironment());
// Matching environment or no environment on attribute
if (!IIEnv || (!TargetEnv.empty() && IIEnv->getName() == TargetEnv)) {
if (Message) {
Expand Down
55 changes: 41 additions & 14 deletions clang/lib/AST/DeclPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out,
Out << Proto;
}

static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy,
static void maybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy,
QualType T,
llvm::raw_ostream &Out) {
StringRef prefix = T->isClassType() ? "class "
Expand All @@ -643,6 +643,22 @@ static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy,
Out << prefix;
}

/// Return the language of the linkage spec of `D`, if applicable.
///
/// \Return - "C" if `D` has been declared with unbraced `extern "C"`
/// - "C++" if `D` has been declared with unbraced `extern "C++"`
/// - nullptr in any other case
static const char *tryGetUnbracedLinkageLanguage(const Decl *D) {
const auto *SD = dyn_cast<LinkageSpecDecl>(D->getDeclContext());
if (!SD || SD->hasBraces())
return nullptr;
if (SD->getLanguage() == LinkageSpecLanguageIDs::C)
return "C";
assert(SD->getLanguage() == LinkageSpecLanguageIDs::CXX &&
"unknown language in linkage specification");
return "C++";
}

void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (!D->getDescribedFunctionTemplate() &&
!D->isFunctionTemplateSpecialization()) {
Expand All @@ -662,6 +678,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D);
if (!Policy.SuppressSpecifiers) {
if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
// the "extern" specifier is implicit
assert(D->getStorageClass() == SC_None);
Out << "extern \"" << Lang << "\" ";
}
switch (D->getStorageClass()) {
case SC_None: break;
case SC_Extern: Out << "extern "; break;
Expand Down Expand Up @@ -807,7 +828,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
}
if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
!Policy.SuppressUnwrittenScope)
MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
maybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
Out);
AFT->getReturnType().print(Out, Policy, Proto);
Proto.clear();
Expand Down Expand Up @@ -932,6 +953,11 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
: D->getASTContext().getUnqualifiedObjCPointerType(D->getType());

if (!Policy.SuppressSpecifiers) {
if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
// the "extern" specifier is implicit
assert(D->getStorageClass() == SC_None);
Out << "extern \"" << Lang << "\" ";
}
StorageClass SC = D->getStorageClass();
if (SC != SC_None)
Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
Expand Down Expand Up @@ -961,7 +987,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {

if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
!Policy.SuppressUnwrittenScope)
MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
maybePrintTagKeywordIfSupressingScopes(Policy, T, Out);

printDeclType(T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
D->getIdentifier())
Expand Down Expand Up @@ -1064,6 +1090,8 @@ void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {

void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
prettyPrintAttributes(D);
if (const char *Lang = tryGetUnbracedLinkageLanguage(D))
Out << "extern \"" << Lang << "\";";
}

void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
Expand Down Expand Up @@ -1136,22 +1164,21 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
}

void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
const char *l;
if (!D->hasBraces()) {
VisitDeclContext(D);
return;
}
const char *L;
if (D->getLanguage() == LinkageSpecLanguageIDs::C)
l = "C";
L = "C";
else {
assert(D->getLanguage() == LinkageSpecLanguageIDs::CXX &&
"unknown language in linkage specification");
l = "C++";
L = "C++";
}

Out << "extern \"" << l << "\" ";
if (D->hasBraces()) {
Out << "{\n";
VisitDeclContext(D);
Indent() << "}";
} else
Visit(*D->decls_begin());
Out << "extern \"" << L << "\" {\n";
VisitDeclContext(D);
Indent() << "}";
}

void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params,
Expand Down
11 changes: 1 addition & 10 deletions clang/lib/AST/TemplateBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,16 +544,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
break;

case Template: {
TemplateName TN = getAsTemplate();
if (const auto *TD = TN.getAsTemplateDecl();
TD && TD->getDeclName().isEmpty()) {
assert(isa<TemplateTemplateParmDecl>(TD) &&
"Unexpected anonymous template");
const auto *TTP = cast<TemplateTemplateParmDecl>(TD);
Out << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex();
} else {
TN.print(Out, Policy);
}
getAsTemplate().print(Out, Policy);
break;
}

Expand Down
14 changes: 14 additions & 0 deletions clang/lib/AST/TemplateName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,14 @@ void TemplateName::Profile(llvm::FoldingSetNodeID &ID) {

void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
Qualified Qual) const {
auto handleAnonymousTTP = [](TemplateDecl *TD, raw_ostream &OS) {
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(TD);
TTP && TTP->getIdentifier() == nullptr) {
OS << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex();
return true;
}
return false;
};
if (NameKind Kind = getKind();
Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {
// After `namespace ns { using std::vector }`, what is the fully-qualified
Expand All @@ -304,6 +312,8 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
// names more often than to export them, thus using the original name is
// most useful in this case.
TemplateDecl *Template = getAsTemplateDecl();
if (handleAnonymousTTP(Template, OS))
return;
if (Qual == Qualified::None)
OS << *Template;
else
Expand All @@ -320,6 +330,10 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
Underlying.getKind() == TemplateName::UsingTemplate);

TemplateDecl *UTD = Underlying.getAsTemplateDecl();

if (handleAnonymousTTP(UTD, OS))
return;

if (IdentifierInfo *II = UTD->getIdentifier();
Policy.CleanUglifiedParameters && II &&
isa<TemplateTemplateParmDecl>(UTD))
Expand Down
43 changes: 32 additions & 11 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,32 @@ void TextNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) {
dumpTemplateArgument(TA);
}

void TextNodeDumper::dumpTemplateName(TemplateName TN) {
void TextNodeDumper::dumpTemplateName(TemplateName TN, StringRef Label) {
AddChild(Label, [=] {
{
llvm::SmallString<128> Str;
{
llvm::raw_svector_ostream SS(Str);
TN.print(SS, PrintPolicy);
}
OS << " '" << Str << "'";

if (TemplateName CanonTN = Context->getCanonicalTemplateName(TN);
CanonTN != TN) {
llvm::SmallString<128> CanonStr;
{
llvm::raw_svector_ostream SS(CanonStr);
CanonTN.print(SS, PrintPolicy);
}
if (CanonStr != Str)
OS << ":'" << CanonStr << "'";
}
}
dumpBareTemplateName(TN);
});
}

void TextNodeDumper::dumpBareTemplateName(TemplateName TN) {
switch (TN.getKind()) {
case TemplateName::Template:
AddChild([=] { Visit(TN.getAsTemplateDecl()); });
Expand All @@ -1143,7 +1168,7 @@ void TextNodeDumper::dumpTemplateName(TemplateName TN) {
if (QTN->hasTemplateKeyword())
OS << " keyword";
dumpNestedNameSpecifier(QTN->getQualifier());
dumpTemplateName(QTN->getUnderlyingTemplate());
dumpBareTemplateName(QTN->getUnderlyingTemplate());
return;
}
case TemplateName::DependentTemplate: {
Expand All @@ -1162,7 +1187,7 @@ void TextNodeDumper::dumpTemplateName(TemplateName TN) {
if (const TemplateTemplateParmDecl *P = STS->getParameter())
AddChild("parameter", [=] { Visit(P); });
dumpDeclRef(STS->getAssociatedDecl(), "associated");
AddChild("replacement", [=] { dumpTemplateName(STS->getReplacement()); });
dumpTemplateName(STS->getReplacement(), "replacement");
return;
}
// FIXME: Implement these.
Expand All @@ -1182,14 +1207,14 @@ void TextNodeDumper::dumpTemplateName(TemplateName TN) {
void TextNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {
OS << " template";
dumpTemplateArgument(TA);
dumpTemplateName(TA.getAsTemplate());
dumpBareTemplateName(TA.getAsTemplate());
}

void TextNodeDumper::VisitTemplateExpansionTemplateArgument(
const TemplateArgument &TA) {
OS << " template expansion";
dumpTemplateArgument(TA);
dumpTemplateName(TA.getAsTemplateOrTemplatePattern());
dumpBareTemplateName(TA.getAsTemplateOrTemplatePattern());
}

void TextNodeDumper::VisitExpressionTemplateArgument(
Expand Down Expand Up @@ -1989,18 +2014,14 @@ void TextNodeDumper::VisitAutoType(const AutoType *T) {

void TextNodeDumper::VisitDeducedTemplateSpecializationType(
const DeducedTemplateSpecializationType *T) {
if (T->getTemplateName().getAsUsingShadowDecl())
OS << " using";
dumpTemplateName(T->getTemplateName(), "name");
}

void TextNodeDumper::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
if (T->isTypeAlias())
OS << " alias";
if (T->getTemplateName().getAsUsingShadowDecl())
OS << " using";
OS << " ";
T->getTemplateName().dump(OS);
dumpTemplateName(T->getTemplateName(), "name");
}

void TextNodeDumper::VisitInjectedClassNameType(
Expand Down
31 changes: 31 additions & 0 deletions clang/lib/Basic/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,8 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasFullBFloat16 = true;
} else if (Feature == "+egpr") {
HasEGPR = true;
} else if (Feature == "+inline-asm-use-gpr32") {
HasInlineAsmUseGPR32 = true;
} else if (Feature == "+push2pop2") {
HasPush2Pop2 = true;
} else if (Feature == "+ppx") {
Expand Down Expand Up @@ -963,6 +965,8 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
// Condition here is aligned with the feature set of mapxf in Options.td
if (HasEGPR && HasPush2Pop2 && HasPPX && HasNDD && HasCCMP && HasNF)
Builder.defineMacro("__APX_F__");
if (HasEGPR && HasInlineAsmUseGPR32)
Builder.defineMacro("__APX_INLINE_ASM_USE_GPR32__");

// Each case falls through to the previous one here.
switch (SSELevel) {
Expand Down Expand Up @@ -1478,6 +1482,18 @@ bool X86TargetInfo::validateAsmConstraint(
case 'C': // SSE floating point constant.
case 'G': // x87 floating point constant.
return true;
case 'j':
Name++;
switch (*Name) {
default:
return false;
case 'r':
Info.setAllowsRegister();
return true;
case 'R':
Info.setAllowsRegister();
return true;
}
case '@':
// CC condition changes.
if (auto Len = matchAsmCCConstraint(Name)) {
Expand Down Expand Up @@ -1750,6 +1766,21 @@ std::string X86TargetInfo::convertConstraint(const char *&Constraint) const {
return std::string("^") + std::string(Constraint++, 2);
}
[[fallthrough]];
case 'j':
switch (Constraint[1]) {
default:
// Break from inner switch and fall through (copy single char),
// continue parsing after copying the current constraint into
// the return string.
break;
case 'r':
case 'R':
// "^" hints llvm that this is a 2 letter constraint.
// "Constraint++" is used to promote the string iterator
// to the next constraint.
return std::string("^") + std::string(Constraint++, 2);
}
[[fallthrough]];
default:
return std::string(1, *Constraint);
}
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 @@ -172,6 +172,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
bool HasCCMP = false;
bool HasNF = false;
bool HasCF = false;
bool HasInlineAsmUseGPR32 = false;

protected:
llvm::X86::CPUKind CPU = llvm::X86::CK_None;
Expand Down
6 changes: 1 addition & 5 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5978,11 +5978,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
auto Name = CGM.getCUDARuntime().getDeviceSideName(
cast<DeclRefExpr>(E->getArg(0)->IgnoreImpCasts())->getDecl());
auto Str = CGM.GetAddrOfConstantCString(Name, "");
llvm::Constant *Zeros[] = {llvm::ConstantInt::get(SizeTy, 0),
llvm::ConstantInt::get(SizeTy, 0)};
auto *Ptr = llvm::ConstantExpr::getGetElementPtr(Str.getElementType(),
Str.getPointer(), Zeros);
return RValue::get(Ptr);
return RValue::get(Str.getPointer());
}
}

Expand Down
10 changes: 2 additions & 8 deletions clang/lib/CodeGen/CGCUDANV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ class CGNVCUDARuntime : public CGCUDARuntime {
bool RelocatableDeviceCode;
/// Mangle context for device.
std::unique_ptr<MangleContext> DeviceMC;
/// Some zeros used for GEPs.
llvm::Constant *Zeros[2];

llvm::FunctionCallee getSetupArgumentFn() const;
llvm::FunctionCallee getLaunchFn() const;
Expand All @@ -91,9 +89,7 @@ class CGNVCUDARuntime : public CGCUDARuntime {
/// where the C code specifies const char*.
llvm::Constant *makeConstantString(const std::string &Str,
const std::string &Name = "") {
auto ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
return llvm::ConstantExpr::getGetElementPtr(ConstStr.getElementType(),
ConstStr.getPointer(), Zeros);
return CGM.GetAddrOfConstantCString(Str, Name.c_str()).getPointer();
}

/// Helper function which generates an initialized constant array from Str,
Expand All @@ -117,7 +113,7 @@ class CGNVCUDARuntime : public CGCUDARuntime {
}
if (Alignment)
GV->setAlignment(llvm::Align(Alignment));
return llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros);
return GV;
}

/// Helper function that generates an empty dummy function returning void.
Expand Down Expand Up @@ -230,8 +226,6 @@ CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM)
IntTy = CGM.IntTy;
SizeTy = CGM.SizeTy;
VoidTy = CGM.VoidTy;
Zeros[0] = llvm::ConstantInt::get(SizeTy, 0);
Zeros[1] = Zeros[0];
PtrTy = CGM.UnqualPtrTy;
}

Expand Down
84 changes: 0 additions & 84 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5737,90 +5737,6 @@ void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var,
Var->addDebugInfo(GVE);
}

void CGDebugInfo::EmitPseudoVariable(CGBuilderTy &Builder,
llvm::Instruction *Value, QualType Ty) {
// Only when -g2 or above is specified, debug info for variables will be
// generated.
if (CGM.getCodeGenOpts().getDebugInfo() <=
llvm::codegenoptions::DebugLineTablesOnly)
return;

llvm::DebugLoc SaveDebugLoc = Builder.getCurrentDebugLocation();
if (!SaveDebugLoc.get())
return;

llvm::DIFile *Unit = SaveDebugLoc->getFile();
llvm::DIType *Type = getOrCreateType(Ty, Unit);

// Check if Value is already a declared variable and has debug info, in this
// case we have nothing to do. Clang emits declared variable as alloca, and
// it is loaded upon use, so we identify such pattern here.
if (llvm::LoadInst *Load = dyn_cast<llvm::LoadInst>(Value)) {
llvm::Value *Var = Load->getPointerOperand();
if (llvm::Metadata *MDValue = llvm::ValueAsMetadata::getIfExists(Var)) {
if (llvm::Value *DbgValue = llvm::MetadataAsValue::getIfExists(
CGM.getLLVMContext(), MDValue)) {
for (llvm::User *U : DbgValue->users()) {
if (llvm::CallInst *DbgDeclare = dyn_cast<llvm::CallInst>(U)) {
if (DbgDeclare->getCalledFunction()->getIntrinsicID() ==
llvm::Intrinsic::dbg_declare &&
DbgDeclare->getArgOperand(0) == DbgValue) {
// There can be implicit type cast applied on a variable if it is
// an opaque ptr, in this case its debug info may not match the
// actual type of object being used as in the next instruction, so
// we will need to emit a pseudo variable for type-casted value.
llvm::DILocalVariable *MDNode = cast<llvm::DILocalVariable>(
cast<llvm::MetadataAsValue>(DbgDeclare->getOperand(1))
->getMetadata());
if (MDNode->getType() == Type)
return;
}
}
}
}
}
}

// Find the correct location to insert a sequence of instructions to
// materialize Value on the stack.
auto SaveInsertionPoint = Builder.saveIP();
if (llvm::InvokeInst *Invoke = dyn_cast<llvm::InvokeInst>(Value))
Builder.SetInsertPoint(Invoke->getNormalDest()->begin());
else if (llvm::Instruction *Next = Value->getIterator()->getNextNode())
Builder.SetInsertPoint(Next);
else
Builder.SetInsertPoint(Value->getParent());
llvm::DebugLoc DL = Value->getDebugLoc();
if (DL.get())
Builder.SetCurrentDebugLocation(DL);
else if (!Builder.getCurrentDebugLocation().get())
Builder.SetCurrentDebugLocation(SaveDebugLoc);

llvm::AllocaInst *PseudoVar = Builder.CreateAlloca(Value->getType());
Address PseudoVarAddr(PseudoVar, Value->getType(),
CharUnits::fromQuantity(PseudoVar->getAlign()));
llvm::LoadInst *Load = Builder.CreateLoad(PseudoVarAddr);
Value->replaceAllUsesWith(Load);
Builder.SetInsertPoint(Load);
Builder.CreateStore(Value, PseudoVarAddr);

// Emit debug info for materialized Value.
unsigned Line = Builder.getCurrentDebugLocation().getLine();
unsigned Column = Builder.getCurrentDebugLocation().getCol();
llvm::DILocalVariable *D = DBuilder.createAutoVariable(
LexicalBlockStack.back(), "", nullptr, 0, Type, false,
llvm::DINode::FlagArtificial);
llvm::DILocation *DIL =
llvm::DILocation::get(CGM.getLLVMContext(), Line, Column,
LexicalBlockStack.back(), CurInlinedAt);
SmallVector<uint64_t> Expr;
DBuilder.insertDeclare(PseudoVar, D, DBuilder.createExpression(Expr), DIL,
Load);

Builder.restoreIP(SaveInsertionPoint);
Builder.SetCurrentDebugLocation(SaveDebugLoc);
}

void CGDebugInfo::EmitGlobalAlias(const llvm::GlobalValue *GV,
const GlobalDecl GD) {

Expand Down
6 changes: 0 additions & 6 deletions clang/lib/CodeGen/CGDebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -529,12 +529,6 @@ class CGDebugInfo {
/// Emit information about an external variable.
void EmitExternalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);

/// Emit a pseudo variable and debug info for an intermediate value if it does
/// not correspond to a variable in the source code, so that a profiler can
/// track more accurate usage of certain instructions of interest.
void EmitPseudoVariable(CGBuilderTy &Builder, llvm::Instruction *Value,
QualType Ty);

/// Emit information about global variable alias.
void EmitGlobalAlias(const llvm::GlobalValue *GV, const GlobalDecl Decl);

Expand Down
7 changes: 2 additions & 5 deletions clang/lib/CodeGen/CGExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,11 +448,7 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
AggValueSlot Dest = EnsureSlot(E->getType());
LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType());
LValue Start = CGF.EmitLValueForFieldInitialization(DestLV, *Field);
llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0);
llvm::Value *IdxStart[] = { Zero, Zero };
llvm::Value *ArrayStart = Builder.CreateInBoundsGEP(
ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxStart,
"arraystart");
llvm::Value *ArrayStart = ArrayPtr.emitRawPointer(CGF);
CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start);
++Field;

Expand All @@ -467,6 +463,7 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
Ctx.hasSameType(Field->getType()->getPointeeType(),
ArrayType->getElementType())) {
// End pointer.
llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0);
llvm::Value *IdxEnd[] = { Zero, Size };
llvm::Value *ArrayEnd = Builder.CreateInBoundsGEP(
ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxEnd,
Expand Down
21 changes: 1 addition & 20 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1937,26 +1937,7 @@ Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
}
}

llvm::Value *Result = EmitLoadOfLValue(E);

// If -fdebug-info-for-profiling is specified, emit a pseudo variable and its
// debug info for the pointer, even if there is no variable associated with
// the pointer's expression.
if (CGF.CGM.getCodeGenOpts().DebugInfoForProfiling && CGF.getDebugInfo()) {
if (llvm::LoadInst *Load = dyn_cast<llvm::LoadInst>(Result)) {
if (llvm::GetElementPtrInst *GEP =
dyn_cast<llvm::GetElementPtrInst>(Load->getPointerOperand())) {
if (llvm::Instruction *Pointer =
dyn_cast<llvm::Instruction>(GEP->getPointerOperand())) {
QualType Ty = E->getBase()->getType();
if (!E->isArrow())
Ty = CGF.getContext().getPointerType(Ty);
CGF.getDebugInfo()->EmitPseudoVariable(Builder, Pointer, Ty);
}
}
}
}
return Result;
return EmitLoadOfLValue(E);
}

Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
Expand Down
9 changes: 3 additions & 6 deletions clang/lib/CodeGen/CGObjCGNU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,7 @@ class CGObjCGNU : public CGObjCRuntime {
llvm::Constant *MakeConstantString(StringRef Str, const char *Name = "") {
ConstantAddress Array =
CGM.GetAddrOfConstantCString(std::string(Str), Name);
return llvm::ConstantExpr::getGetElementPtr(Array.getElementType(),
Array.getPointer(), Zeros);
return Array.getPointer();
}

/// Emits a linkonce_odr string, whose name is the prefix followed by the
Expand All @@ -221,8 +220,7 @@ class CGObjCGNU : public CGObjCRuntime {
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
ConstStr = GV;
}
return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
ConstStr, Zeros);
return ConstStr;
}

/// Returns a property name and encoding string.
Expand Down Expand Up @@ -1477,8 +1475,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
TypesGlobal = GV;
}
return llvm::ConstantExpr::getGetElementPtr(TypesGlobal->getValueType(),
TypesGlobal, Zeros);
return TypesGlobal;
}
llvm::Constant *GetConstantSelector(Selector Sel,
const std::string &TypeEncoding) override {
Expand Down
11 changes: 2 additions & 9 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6131,9 +6131,6 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
return ConstantAddress(
C, C->getValueType(), CharUnits::fromQuantity(C->getAlignment()));

llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty);
llvm::Constant *Zeros[] = { Zero, Zero };

const ASTContext &Context = getContext();
const llvm::Triple &Triple = getTriple();

Expand Down Expand Up @@ -6204,8 +6201,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {

// Decay array -> ptr
CFConstantStringClassRef =
IsSwiftABI ? llvm::ConstantExpr::getPtrToInt(C, Ty)
: llvm::ConstantExpr::getGetElementPtr(Ty, C, Zeros);
IsSwiftABI ? llvm::ConstantExpr::getPtrToInt(C, Ty) : C;
}

QualType CFTy = Context.getCFConstantStringType();
Expand Down Expand Up @@ -6261,10 +6257,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
GV->setSection(".rodata");

// String.
llvm::Constant *Str =
llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros);

Fields.add(Str);
Fields.add(GV);

// String length.
llvm::IntegerType *LengthTy =
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Driver/ToolChains/Arch/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,6 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back("+prefer-no-gather");
if (Args.hasArg(options::OPT_mno_scatter))
Features.push_back("+prefer-no-scatter");
if (Args.hasArg(options::OPT_mapx_inline_asm_use_gpr32))
Features.push_back("+inline-asm-use-gpr32");
}
29 changes: 0 additions & 29 deletions clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -672,41 +672,12 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}

// Facebook T92898286
if (Args.hasArg(options::OPT_post_link_optimize))
CmdArgs.push_back("-q");
// End Facebook T92898286

Args.AddAllArgs(CmdArgs, options::OPT_T);

const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
C.addCommand(std::make_unique<Command>(JA, *this,
ResponseFileSupport::AtFileCurCP(),
Exec, CmdArgs, Inputs, Output));
// Facebook T92898286
if (!Args.hasArg(options::OPT_post_link_optimize) || !Output.isFilename())
return;

const char *MvExec = Args.MakeArgString(ToolChain.GetProgramPath("mv"));
ArgStringList MoveCmdArgs;
MoveCmdArgs.push_back(Output.getFilename());
const char *PreBoltBin =
Args.MakeArgString(Twine(Output.getFilename()) + ".pre-bolt");
MoveCmdArgs.push_back(PreBoltBin);
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
MvExec, MoveCmdArgs, std::nullopt));

ArgStringList BoltCmdArgs;
const char *BoltExec =
Args.MakeArgString(ToolChain.GetProgramPath("llvm-bolt"));
BoltCmdArgs.push_back(PreBoltBin);
BoltCmdArgs.push_back("-reorder-blocks=reverse");
BoltCmdArgs.push_back("-update-debug-sections");
BoltCmdArgs.push_back("-o");
BoltCmdArgs.push_back(Output.getFilename());
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
BoltExec, BoltCmdArgs, std::nullopt));
// End Facebook T92898286
}

void tools::gnutools::Assembler::ConstructJob(Compilation &C,
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4026,6 +4026,9 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
if (AngleNestingLevel == 0) {
if (FormatTok->is(tok::colon)) {
IsDerived = true;
} else if (FormatTok->is(tok::identifier) &&
FormatTok->Previous->is(tok::coloncolon)) {
ClassName = FormatTok;
} else if (FormatTok->is(tok::l_paren) &&
IsNonMacroIdentifier(FormatTok->Previous)) {
break;
Expand Down
65 changes: 27 additions & 38 deletions clang/lib/Parse/ParseOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/EnterExpressionEvaluationContext.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaAMDGPU.h"
#include "clang/Sema/SemaCodeCompletion.h"
#include "clang/Sema/SemaOpenMP.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Frontend/OpenMP/OMPAssume.h"
#include "llvm/Frontend/OpenMP/OMPContext.h"
#include <bitset>
#include <optional>

using namespace clang;
Expand Down Expand Up @@ -1645,19 +1646,17 @@ bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
SmallVectorImpl<OMPClause *> &Clauses,
SourceLocation Loc) {
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
llvm::omp::Clause_enumSize + 1>
FirstClauses(llvm::omp::Clause_enumSize + 1);
std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OpenMPClauseKind CKind = Tok.isAnnotation()
? OMPC_unknown
: getOpenMPClauseKind(PP.getSpelling(Tok));
Actions.OpenMP().StartOpenMPClause(CKind);
OMPClause *Clause = ParseOpenMPClause(
DKind, CKind, !FirstClauses[unsigned(CKind)].getInt());
OMPClause *Clause =
ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
StopBeforeMatch);
FirstClauses[unsigned(CKind)].setInt(true);
SeenClauses[unsigned(CKind)] = true;
if (Clause != nullptr)
Clauses.push_back(Clause);
if (Tok.is(tok::annot_pragma_openmp_end)) {
Expand Down Expand Up @@ -2113,19 +2112,17 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
/*AllowScopeSpecifier=*/true)) {
SmallVector<OMPClause *, 1> Clauses;
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
llvm::omp::Clause_enumSize + 1>
FirstClauses(llvm::omp::Clause_enumSize + 1);
std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OpenMPClauseKind CKind =
Tok.isAnnotation() ? OMPC_unknown
: getOpenMPClauseKind(PP.getSpelling(Tok));
Actions.OpenMP().StartOpenMPClause(CKind);
OMPClause *Clause = ParseOpenMPClause(
OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt());
OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
!SeenClauses[unsigned(CKind)]);
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
StopBeforeMatch);
FirstClauses[unsigned(CKind)].setInt(true);
SeenClauses[unsigned(CKind)] = true;
if (Clause != nullptr)
Clauses.push_back(Clause);
if (Tok.is(tok::annot_pragma_openmp_end)) {
Expand All @@ -2149,9 +2146,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_requires: {
SourceLocation StartLoc = ConsumeToken();
SmallVector<OMPClause *, 5> Clauses;
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
llvm::omp::Clause_enumSize + 1>
FirstClauses(llvm::omp::Clause_enumSize + 1);
std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
if (Tok.is(tok::annot_pragma_openmp_end)) {
Diag(Tok, diag::err_omp_expected_clause)
<< getOpenMPDirectiveName(OMPD_requires);
Expand All @@ -2162,11 +2157,11 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
? OMPC_unknown
: getOpenMPClauseKind(PP.getSpelling(Tok));
Actions.OpenMP().StartOpenMPClause(CKind);
OMPClause *Clause = ParseOpenMPClause(
OMPD_requires, CKind, !FirstClauses[unsigned(CKind)].getInt());
OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
!SeenClauses[unsigned(CKind)]);
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
StopBeforeMatch);
FirstClauses[unsigned(CKind)].setInt(true);
SeenClauses[unsigned(CKind)] = true;
if (Clause != nullptr)
Clauses.push_back(Clause);
if (Tok.is(tok::annot_pragma_openmp_end)) {
Expand Down Expand Up @@ -2509,9 +2504,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
ParsingOpenMPDirectiveRAII DirScope(*this);
ParenBraceBracketBalancer BalancerRAIIObj(*this);
SmallVector<OMPClause *, 5> Clauses;
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
llvm::omp::Clause_enumSize + 1>
FirstClauses(llvm::omp::Clause_enumSize + 1);
std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
SourceLocation Loc = ReadDirectiveWithinMetadirective
Expand Down Expand Up @@ -2716,19 +2709,17 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
/*AllowScopeSpecifier=*/false)) {
SmallVector<OMPClause *, 1> Clauses;
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
llvm::omp::Clause_enumSize + 1>
FirstClauses(llvm::omp::Clause_enumSize + 1);
std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OpenMPClauseKind CKind =
Tok.isAnnotation() ? OMPC_unknown
: getOpenMPClauseKind(PP.getSpelling(Tok));
Actions.OpenMP().StartOpenMPClause(CKind);
OMPClause *Clause = ParseOpenMPClause(
OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt());
OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
!SeenClauses[unsigned(CKind)]);
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
StopBeforeMatch);
FirstClauses[unsigned(CKind)].setInt(true);
SeenClauses[unsigned(CKind)] = true;
if (Clause != nullptr)
Clauses.push_back(Clause);
if (Tok.is(tok::annot_pragma_openmp_end)) {
Expand Down Expand Up @@ -2925,13 +2916,11 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
ImplicitClauseAllowed = false;
Actions.OpenMP().StartOpenMPClause(CKind);
HasImplicitClause = false;
OMPClause *Clause = ParseOpenMPClause(
DKind, CKind, !FirstClauses[unsigned(CKind)].getInt());
FirstClauses[unsigned(CKind)].setInt(true);
if (Clause) {
FirstClauses[unsigned(CKind)].setPointer(Clause);
OMPClause *Clause =
ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
SeenClauses[unsigned(CKind)] = true;
if (Clause)
Clauses.push_back(Clause);
}

// Skip ',' if any.
if (Tok.is(tok::comma))
Expand All @@ -2947,7 +2936,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
// If the depend or doacross clause is specified, the ordered construct
// is a stand-alone directive.
for (auto CK : {OMPC_depend, OMPC_doacross}) {
if (FirstClauses[unsigned(CK)].getInt()) {
if (SeenClauses[unsigned(CK)]) {
if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
ParsedStmtContext()) {
Diag(Loc, diag::err_omp_immediate_directive)
Expand All @@ -2959,7 +2948,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
}
}

if (DKind == OMPD_tile && !FirstClauses[unsigned(OMPC_sizes)].getInt()) {
if (DKind == OMPD_tile && !SeenClauses[unsigned(OMPC_sizes)]) {
Diag(Loc, diag::err_omp_required_clause)
<< getOpenMPDirectiveName(OMPD_tile) << "sizes";
}
Expand Down Expand Up @@ -3757,15 +3746,15 @@ OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
if (!PA.checkExactlyNumArgs(Actions, 2))
continue;
if (auto *A = Actions.CreateAMDGPUFlatWorkGroupSizeAttr(
if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(
PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
Attrs.push_back(A);
continue;
case ParsedAttr::AT_AMDGPUWavesPerEU:
if (!PA.checkAtLeastNumArgs(Actions, 1) ||
!PA.checkAtMostNumArgs(Actions, 2))
continue;
if (auto *A = Actions.CreateAMDGPUWavesPerEUAttr(
if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(
PA, PA.getArgAsExpr(0),
PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
Attrs.push_back(A);
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Sema/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,13 @@ add_clang_library(clangSema
Scope.cpp
ScopeInfo.cpp
Sema.cpp
SemaAMDGPU.cpp
SemaARM.cpp
SemaAccess.cpp
SemaAttr.cpp
SemaAPINotes.cpp
SemaAvailability.cpp
SemaBPF.cpp
SemaBase.cpp
SemaCXXScopeSpec.cpp
SemaCast.cpp
Expand All @@ -50,27 +53,34 @@ add_clang_library(clangSema
SemaExprObjC.cpp
SemaFixItUtils.cpp
SemaHLSL.cpp
SemaHexagon.cpp
SemaInit.cpp
SemaLambda.cpp
SemaLookup.cpp
SemaLoongArch.cpp
SemaMIPS.cpp
SemaModule.cpp
SemaNVPTX.cpp
SemaObjC.cpp
SemaObjCProperty.cpp
SemaOpenACC.cpp
SemaOpenMP.cpp
SemaOverload.cpp
SemaPPC.cpp
SemaPseudoObject.cpp
SemaRISCV.cpp
SemaStmt.cpp
SemaStmtAsm.cpp
SemaStmtAttr.cpp
SemaSYCL.cpp
SemaSystemZ.cpp
SemaTemplate.cpp
SemaTemplateDeduction.cpp
SemaTemplateInstantiate.cpp
SemaTemplateInstantiateDecl.cpp
SemaTemplateVariadic.cpp
SemaType.cpp
SemaWasm.cpp
SemaX86.cpp
TypeLocBuilder.cpp

Expand Down
24 changes: 24 additions & 0 deletions clang/lib/Sema/Sema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,27 @@
#include "clang/Sema/RISCVIntrinsicManager.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaAMDGPU.h"
#include "clang/Sema/SemaARM.h"
#include "clang/Sema/SemaBPF.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaCodeCompletion.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Sema/SemaHLSL.h"
#include "clang/Sema/SemaHexagon.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaLoongArch.h"
#include "clang/Sema/SemaMIPS.h"
#include "clang/Sema/SemaNVPTX.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenACC.h"
#include "clang/Sema/SemaOpenMP.h"
#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaPseudoObject.h"
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSYCL.h"
#include "clang/Sema/SemaSystemZ.h"
#include "clang/Sema/SemaWasm.h"
#include "clang/Sema/SemaX86.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/TemplateInstCallback.h"
Expand Down Expand Up @@ -206,16 +216,26 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr),
OpaqueParser(nullptr), CurContext(nullptr), ExternalSource(nullptr),
CurScope(nullptr), Ident_super(nullptr),
AMDGPUPtr(std::make_unique<SemaAMDGPU>(*this)),
ARMPtr(std::make_unique<SemaARM>(*this)),
BPFPtr(std::make_unique<SemaBPF>(*this)),
CodeCompletionPtr(
std::make_unique<SemaCodeCompletion>(*this, CodeCompleter)),
CUDAPtr(std::make_unique<SemaCUDA>(*this)),
HLSLPtr(std::make_unique<SemaHLSL>(*this)),
HexagonPtr(std::make_unique<SemaHexagon>(*this)),
LoongArchPtr(std::make_unique<SemaLoongArch>(*this)),
MIPSPtr(std::make_unique<SemaMIPS>(*this)),
NVPTXPtr(std::make_unique<SemaNVPTX>(*this)),
ObjCPtr(std::make_unique<SemaObjC>(*this)),
OpenACCPtr(std::make_unique<SemaOpenACC>(*this)),
OpenMPPtr(std::make_unique<SemaOpenMP>(*this)),
PPCPtr(std::make_unique<SemaPPC>(*this)),
PseudoObjectPtr(std::make_unique<SemaPseudoObject>(*this)),
RISCVPtr(std::make_unique<SemaRISCV>(*this)),
SYCLPtr(std::make_unique<SemaSYCL>(*this)),
SystemZPtr(std::make_unique<SemaSystemZ>(*this)),
WasmPtr(std::make_unique<SemaWasm>(*this)),
X86Ptr(std::make_unique<SemaX86>(*this)),
MSPointerToMemberRepresentationMethod(
LangOpts.getMSPointerToMemberRepresentationMethod()),
Expand Down Expand Up @@ -1357,6 +1377,10 @@ void Sema::ActOnEndOfTranslationUnit() {
Consumer.CompleteExternalDeclaration(D);
}

if (LangOpts.HLSL)
HLSL().DiagnoseAvailabilityViolations(
getASTContext().getTranslationUnitDecl());

// If there were errors, disable 'unused' warnings since they will mostly be
// noise. Don't warn for a use from a module: either we should warn on all
// file-scope declarations in modules or not at all, but whether the
Expand Down
311 changes: 311 additions & 0 deletions clang/lib/Sema/SemaAMDGPU.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,311 @@
//===------ SemaAMDGPU.cpp ------- AMDGPU target-specific routines --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements semantic analysis functions specific to AMDGPU.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaAMDGPU.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Sema/Ownership.h"
#include "clang/Sema/Sema.h"
#include "llvm/Support/AtomicOrdering.h"
#include <cstdint>

namespace clang {

SemaAMDGPU::SemaAMDGPU(Sema &S) : SemaBase(S) {}

bool SemaAMDGPU::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
// position of memory order and scope arguments in the builtin
unsigned OrderIndex, ScopeIndex;
switch (BuiltinID) {
case AMDGPU::BI__builtin_amdgcn_global_load_lds: {
constexpr const int SizeIdx = 2;
llvm::APSInt Size;
Expr *ArgExpr = TheCall->getArg(SizeIdx);
ExprResult R = SemaRef.VerifyIntegerConstantExpression(ArgExpr, &Size);
if (R.isInvalid())
return true;
switch (Size.getSExtValue()) {
case 1:
case 2:
case 4:
return false;
default:
Diag(ArgExpr->getExprLoc(),
diag::err_amdgcn_global_load_lds_size_invalid_value)
<< ArgExpr->getSourceRange();
Diag(ArgExpr->getExprLoc(),
diag::note_amdgcn_global_load_lds_size_valid_value)
<< ArgExpr->getSourceRange();
return true;
}
}
case AMDGPU::BI__builtin_amdgcn_get_fpenv:
case AMDGPU::BI__builtin_amdgcn_set_fpenv:
return false;
case AMDGPU::BI__builtin_amdgcn_atomic_inc32:
case AMDGPU::BI__builtin_amdgcn_atomic_inc64:
case AMDGPU::BI__builtin_amdgcn_atomic_dec32:
case AMDGPU::BI__builtin_amdgcn_atomic_dec64:
OrderIndex = 2;
ScopeIndex = 3;
break;
case AMDGPU::BI__builtin_amdgcn_fence:
OrderIndex = 0;
ScopeIndex = 1;
break;
default:
return false;
}

ExprResult Arg = TheCall->getArg(OrderIndex);
auto ArgExpr = Arg.get();
Expr::EvalResult ArgResult;

if (!ArgExpr->EvaluateAsInt(ArgResult, getASTContext()))
return Diag(ArgExpr->getExprLoc(), diag::err_typecheck_expect_int)
<< ArgExpr->getType();
auto Ord = ArgResult.Val.getInt().getZExtValue();

// Check validity of memory ordering as per C11 / C++11's memody model.
// Only fence needs check. Atomic dec/inc allow all memory orders.
if (!llvm::isValidAtomicOrderingCABI(Ord))
return Diag(ArgExpr->getBeginLoc(),
diag::warn_atomic_op_has_invalid_memory_order)
<< 0 << ArgExpr->getSourceRange();
switch (static_cast<llvm::AtomicOrderingCABI>(Ord)) {
case llvm::AtomicOrderingCABI::relaxed:
case llvm::AtomicOrderingCABI::consume:
if (BuiltinID == AMDGPU::BI__builtin_amdgcn_fence)
return Diag(ArgExpr->getBeginLoc(),
diag::warn_atomic_op_has_invalid_memory_order)
<< 0 << ArgExpr->getSourceRange();
break;
case llvm::AtomicOrderingCABI::acquire:
case llvm::AtomicOrderingCABI::release:
case llvm::AtomicOrderingCABI::acq_rel:
case llvm::AtomicOrderingCABI::seq_cst:
break;
}

Arg = TheCall->getArg(ScopeIndex);
ArgExpr = Arg.get();
Expr::EvalResult ArgResult1;
// Check that sync scope is a constant literal
if (!ArgExpr->EvaluateAsConstantExpr(ArgResult1, getASTContext()))
return Diag(ArgExpr->getExprLoc(), diag::err_expr_not_string_literal)
<< ArgExpr->getType();

return false;
}

static bool
checkAMDGPUFlatWorkGroupSizeArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr,
const AMDGPUFlatWorkGroupSizeAttr &Attr) {
// Accept template arguments for now as they depend on something else.
// We'll get to check them when they eventually get instantiated.
if (MinExpr->isValueDependent() || MaxExpr->isValueDependent())
return false;

uint32_t Min = 0;
if (!S.checkUInt32Argument(Attr, MinExpr, Min, 0))
return true;

uint32_t Max = 0;
if (!S.checkUInt32Argument(Attr, MaxExpr, Max, 1))
return true;

if (Min == 0 && Max != 0) {
S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
<< &Attr << 0;
return true;
}
if (Min > Max) {
S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
<< &Attr << 1;
return true;
}

return false;
}

AMDGPUFlatWorkGroupSizeAttr *
SemaAMDGPU::CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI,
Expr *MinExpr, Expr *MaxExpr) {
ASTContext &Context = getASTContext();
AMDGPUFlatWorkGroupSizeAttr TmpAttr(Context, CI, MinExpr, MaxExpr);

if (checkAMDGPUFlatWorkGroupSizeArguments(SemaRef, MinExpr, MaxExpr, TmpAttr))
return nullptr;
return ::new (Context)
AMDGPUFlatWorkGroupSizeAttr(Context, CI, MinExpr, MaxExpr);
}

void SemaAMDGPU::addAMDGPUFlatWorkGroupSizeAttr(Decl *D,
const AttributeCommonInfo &CI,
Expr *MinExpr, Expr *MaxExpr) {
if (auto *Attr = CreateAMDGPUFlatWorkGroupSizeAttr(CI, MinExpr, MaxExpr))
D->addAttr(Attr);
}

void SemaAMDGPU::handleAMDGPUFlatWorkGroupSizeAttr(Decl *D,
const ParsedAttr &AL) {
Expr *MinExpr = AL.getArgAsExpr(0);
Expr *MaxExpr = AL.getArgAsExpr(1);

addAMDGPUFlatWorkGroupSizeAttr(D, AL, MinExpr, MaxExpr);
}

static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr,
Expr *MaxExpr,
const AMDGPUWavesPerEUAttr &Attr) {
if (S.DiagnoseUnexpandedParameterPack(MinExpr) ||
(MaxExpr && S.DiagnoseUnexpandedParameterPack(MaxExpr)))
return true;

// Accept template arguments for now as they depend on something else.
// We'll get to check them when they eventually get instantiated.
if (MinExpr->isValueDependent() || (MaxExpr && MaxExpr->isValueDependent()))
return false;

uint32_t Min = 0;
if (!S.checkUInt32Argument(Attr, MinExpr, Min, 0))
return true;

uint32_t Max = 0;
if (MaxExpr && !S.checkUInt32Argument(Attr, MaxExpr, Max, 1))
return true;

if (Min == 0 && Max != 0) {
S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
<< &Attr << 0;
return true;
}
if (Max != 0 && Min > Max) {
S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
<< &Attr << 1;
return true;
}

return false;
}

AMDGPUWavesPerEUAttr *
SemaAMDGPU::CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI,
Expr *MinExpr, Expr *MaxExpr) {
ASTContext &Context = getASTContext();
AMDGPUWavesPerEUAttr TmpAttr(Context, CI, MinExpr, MaxExpr);

if (checkAMDGPUWavesPerEUArguments(SemaRef, MinExpr, MaxExpr, TmpAttr))
return nullptr;

return ::new (Context) AMDGPUWavesPerEUAttr(Context, CI, MinExpr, MaxExpr);
}

void SemaAMDGPU::addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *MinExpr, Expr *MaxExpr) {
if (auto *Attr = CreateAMDGPUWavesPerEUAttr(CI, MinExpr, MaxExpr))
D->addAttr(Attr);
}

void SemaAMDGPU::handleAMDGPUWavesPerEUAttr(Decl *D, const ParsedAttr &AL) {
if (!AL.checkAtLeastNumArgs(SemaRef, 1) || !AL.checkAtMostNumArgs(SemaRef, 2))
return;

Expr *MinExpr = AL.getArgAsExpr(0);
Expr *MaxExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr;

addAMDGPUWavesPerEUAttr(D, AL, MinExpr, MaxExpr);
}

void SemaAMDGPU::handleAMDGPUNumSGPRAttr(Decl *D, const ParsedAttr &AL) {
uint32_t NumSGPR = 0;
Expr *NumSGPRExpr = AL.getArgAsExpr(0);
if (!SemaRef.checkUInt32Argument(AL, NumSGPRExpr, NumSGPR))
return;

D->addAttr(::new (getASTContext())
AMDGPUNumSGPRAttr(getASTContext(), AL, NumSGPR));
}

void SemaAMDGPU::handleAMDGPUNumVGPRAttr(Decl *D, const ParsedAttr &AL) {
uint32_t NumVGPR = 0;
Expr *NumVGPRExpr = AL.getArgAsExpr(0);
if (!SemaRef.checkUInt32Argument(AL, NumVGPRExpr, NumVGPR))
return;

D->addAttr(::new (getASTContext())
AMDGPUNumVGPRAttr(getASTContext(), AL, NumVGPR));
}

static bool
checkAMDGPUMaxNumWorkGroupsArguments(Sema &S, Expr *XExpr, Expr *YExpr,
Expr *ZExpr,
const AMDGPUMaxNumWorkGroupsAttr &Attr) {
if (S.DiagnoseUnexpandedParameterPack(XExpr) ||
(YExpr && S.DiagnoseUnexpandedParameterPack(YExpr)) ||
(ZExpr && S.DiagnoseUnexpandedParameterPack(ZExpr)))
return true;

// Accept template arguments for now as they depend on something else.
// We'll get to check them when they eventually get instantiated.
if (XExpr->isValueDependent() || (YExpr && YExpr->isValueDependent()) ||
(ZExpr && ZExpr->isValueDependent()))
return false;

uint32_t NumWG = 0;
Expr *Exprs[3] = {XExpr, YExpr, ZExpr};
for (int i = 0; i < 3; i++) {
if (Exprs[i]) {
if (!S.checkUInt32Argument(Attr, Exprs[i], NumWG, i,
/*StrictlyUnsigned=*/true))
return true;
if (NumWG == 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
<< &Attr << Exprs[i]->getSourceRange();
return true;
}
}
}

return false;
}

AMDGPUMaxNumWorkGroupsAttr *SemaAMDGPU::CreateAMDGPUMaxNumWorkGroupsAttr(
const AttributeCommonInfo &CI, Expr *XExpr, Expr *YExpr, Expr *ZExpr) {
ASTContext &Context = getASTContext();
AMDGPUMaxNumWorkGroupsAttr TmpAttr(Context, CI, XExpr, YExpr, ZExpr);

if (checkAMDGPUMaxNumWorkGroupsArguments(SemaRef, XExpr, YExpr, ZExpr,
TmpAttr))
return nullptr;

return ::new (Context)
AMDGPUMaxNumWorkGroupsAttr(Context, CI, XExpr, YExpr, ZExpr);
}

void SemaAMDGPU::addAMDGPUMaxNumWorkGroupsAttr(Decl *D,
const AttributeCommonInfo &CI,
Expr *XExpr, Expr *YExpr,
Expr *ZExpr) {
if (auto *Attr = CreateAMDGPUMaxNumWorkGroupsAttr(CI, XExpr, YExpr, ZExpr))
D->addAttr(Attr);
}

void SemaAMDGPU::handleAMDGPUMaxNumWorkGroupsAttr(Decl *D,
const ParsedAttr &AL) {
Expr *YExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr;
Expr *ZExpr = (AL.getNumArgs() > 2) ? AL.getArgAsExpr(2) : nullptr;
addAMDGPUMaxNumWorkGroupsAttr(D, AL, AL.getArgAsExpr(0), YExpr, ZExpr);
}

} // namespace clang
Loading