Merge remote-tracking branch 'ms/master' into user/texr/integrate-master

This commit is contained in:
Tex Riddell 2018-07-30 15:36:07 -07:00
Родитель a936c575f1 f9e3d5ea01
Коммит 2f5afecf67
22 изменённых файлов: 876 добавлений и 19 удалений

Просмотреть файл

@ -261,6 +261,8 @@ The namespace ``vk`` will be used for all Vulkan attributes:
and struct fields. and struct fields.
- ``index(X)``: For specifying the index at a specific pixel shader output - ``index(X)``: For specifying the index at a specific pixel shader output
location. Used for dual-source blending. location. Used for dual-source blending.
- ``post_depth_coverage``: The input variable decorated with SampleMask will
reflect the result of the EarlyFragmentTests. Only valid on pixel shader entry points.
Only ``vk::`` attributes in the above list are supported. Other attributes will Only ``vk::`` attributes in the above list are supported. Other attributes will
result in warnings and be ignored by the compiler. All C++11 attributes will result in warnings and be ignored by the compiler. All C++11 attributes will

Просмотреть файл

@ -59,27 +59,30 @@ public:
StackSave->eraseFromParent(); StackSave->eraseFromParent();
StackRestore->eraseFromParent(); StackRestore->eraseFromParent();
// Has stacksave/store mean alloca not in entry block.
if (bUpdated) { // If stacksave/store is present, it means alloca not in the
// Make sure all allocas are in entry block. // entry block. However, there could be other cases where allocas
for (Function &F : M.functions()) { // could be present in the non-entry blocks.
MoveAllocasToEntryBlock(&F); // Therefore, always go through all non-entry blocks and
} // make sure all allocas are moved to the entry block.
for (Function &F : M.functions()) {
bUpdated |= MoveAllocasToEntryBlock(&F);
} }
return bUpdated; return bUpdated;
} }
private: private:
void MoveAllocasToEntryBlock(Function *F); bool MoveAllocasToEntryBlock(Function *F);
}; };
char HLPreprocess::ID = 0; char HLPreprocess::ID = 0;
// Make sure all allocas are in entry block. // Make sure all allocas are in entry block.
void HLPreprocess::MoveAllocasToEntryBlock(Function *F) { bool HLPreprocess::MoveAllocasToEntryBlock(Function *F) {
bool changed = false;
if (F->getBasicBlockList().size() < 2) if (F->getBasicBlockList().size() < 2)
return; return changed;
BasicBlock &Entry = F->getEntryBlock(); BasicBlock &Entry = F->getEntryBlock();
IRBuilder<> Builder(Entry.getFirstInsertionPt()); IRBuilder<> Builder(Entry.getFirstInsertionPt());
@ -92,9 +95,11 @@ void HLPreprocess::MoveAllocasToEntryBlock(Function *F) {
if (isa<AllocaInst>(I)) { if (isa<AllocaInst>(I)) {
I->removeFromParent(); I->removeFromParent();
Builder.Insert(I); Builder.Insert(I);
changed = true;
} }
} }
} }
return changed;
} }
} // namespace } // namespace

Просмотреть файл

@ -401,7 +401,10 @@ void PassManagerBuilder::populateModulePassManager(
//MPM.add(createLoopUnswitchPass(SizeLevel || OptLevel < 3)); // HLSL Change - may move barrier inside divergent if. //MPM.add(createLoopUnswitchPass(SizeLevel || OptLevel < 3)); // HLSL Change - may move barrier inside divergent if.
MPM.add(createInstructionCombiningPass()); MPM.add(createInstructionCombiningPass());
MPM.add(createIndVarSimplifyPass()); // Canonicalize indvars MPM.add(createIndVarSimplifyPass()); // Canonicalize indvars
MPM.add(createLoopIdiomPass()); // Recognize idioms like memset. // HLSL Change Begins
// Don't allow loop idiom pass which may insert memset/memcpy thereby breaking the dxil
//MPM.add(createLoopIdiomPass()); // Recognize idioms like memset.
// HLSL Change Ends
MPM.add(createLoopDeletionPass()); // Delete dead loops MPM.add(createLoopDeletionPass()); // Delete dead loops
if (EnableLoopInterchange) { if (EnableLoopInterchange) {
MPM.add(createLoopInterchangePass()); // Interchange loops MPM.add(createLoopInterchangePass()); // Interchange loops

Просмотреть файл

@ -961,6 +961,13 @@ def VKConstantId : InheritableAttr {
let Documentation = [Undocumented]; let Documentation = [Undocumented];
} }
def VKPostDepthCoverage : InheritableAttr {
let Spellings = [CXX11<"vk", "post_depth_coverage">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let LangOpts = [SPIRV];
let Documentation = [Undocumented];
}
// SPIRV Change Ends // SPIRV Change Ends
def C11NoReturn : InheritableAttr { def C11NoReturn : InheritableAttr {

Просмотреть файл

@ -7547,7 +7547,7 @@ def err_hlsl_unsupported_div_minint : Error<
def err_hlsl_unsupported_mod_double : Error< def err_hlsl_unsupported_mod_double : Error<
"modulo cannot be used with doubles, cast to float first">; "modulo cannot be used with doubles, cast to float first">;
def err_hlsl_unsupported_nested_struct : Error< def err_hlsl_unsupported_nested_struct : Error<
"nested class/struct/interfaces are not supported in HLSL">; "nested named class/struct/interfaces are not supported in HLSL">;
def err_hlsl_unsupported_nested_typedef : Error< def err_hlsl_unsupported_nested_typedef : Error<
"nested typedefs are not supported in HLSL">; "nested typedefs are not supported in HLSL">;
def err_hlsl_unsupported_operator : Error< def err_hlsl_unsupported_operator : Error<

Просмотреть файл

@ -34,6 +34,7 @@ enum class Extension {
KHR_device_group, KHR_device_group,
KHR_multiview, KHR_multiview,
KHR_shader_draw_parameters, KHR_shader_draw_parameters,
KHR_post_depth_coverage,
EXT_descriptor_indexing, EXT_descriptor_indexing,
EXT_fragment_fully_covered, EXT_fragment_fully_covered,
EXT_shader_stencil_export, EXT_shader_stencil_export,

Просмотреть файл

@ -484,6 +484,9 @@ public:
llvm::ArrayRef<uint32_t> constituents); llvm::ArrayRef<uint32_t> constituents);
uint32_t getConstantNull(uint32_t type); uint32_t getConstantNull(uint32_t type);
// === Debug ===
void debugLine(uint32_t file, uint32_t line, uint32_t column);
private: private:
/// \brief Map from basic blocks' <label-id> to their structured /// \brief Map from basic blocks' <label-id> to their structured
/// representation. /// representation.

Просмотреть файл

@ -2891,8 +2891,9 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
NonNestedClass = false; NonNestedClass = false;
// HLSL Change Starts // HLSL Change Starts
if (getLangOpts().HLSL) { if (getLangOpts().HLSL && getLangOpts().HLSLVersion < 2016 &&
Diag(RecordLoc, diag::err_hlsl_unsupported_construct) << "nested class"; cast<NamedDecl>(TagDecl)->getDeclName()) {
Diag(RecordLoc, diag::err_hlsl_unsupported_nested_struct);
break; break;
} else { } else {
// HLSL Change Ends - succeeding block is now conditional // HLSL Change Ends - succeeding block is now conditional

Просмотреть файл

@ -113,6 +113,8 @@ Extension FeatureManager::getExtensionSymbol(llvm::StringRef name) {
Extension::AMD_shader_explicit_vertex_parameter) Extension::AMD_shader_explicit_vertex_parameter)
.Case("SPV_GOOGLE_hlsl_functionality1", .Case("SPV_GOOGLE_hlsl_functionality1",
Extension::GOOGLE_hlsl_functionality1) Extension::GOOGLE_hlsl_functionality1)
.Case("SPV_KHR_post_depth_coverage",
Extension::KHR_post_depth_coverage)
.Default(Extension::Unknown); .Default(Extension::Unknown);
} }
@ -128,6 +130,8 @@ const char *FeatureManager::getExtensionName(Extension symbol) {
return "SPV_KHR_multiview"; return "SPV_KHR_multiview";
case Extension::KHR_shader_draw_parameters: case Extension::KHR_shader_draw_parameters:
return "SPV_KHR_shader_draw_parameters"; return "SPV_KHR_shader_draw_parameters";
case Extension::KHR_post_depth_coverage:
return "SPV_KHR_post_depth_coverage";
case Extension::EXT_descriptor_indexing: case Extension::EXT_descriptor_indexing:
return "SPV_EXT_descriptor_indexing"; return "SPV_EXT_descriptor_indexing";
case Extension::EXT_fragment_fully_covered: case Extension::EXT_fragment_fully_covered:

Просмотреть файл

@ -1258,6 +1258,11 @@ uint32_t ModuleBuilder::getConstantNull(uint32_t typeId) {
return constId; return constId;
} }
void ModuleBuilder::debugLine(uint32_t file, uint32_t line, uint32_t column) {
instBuilder.opLine(file, line, column).x();
insertPoint->appendInstruction(std::move(constructSite));
}
BasicBlock *ModuleBuilder::getBasicBlock(uint32_t labelId) { BasicBlock *ModuleBuilder::getBasicBlock(uint32_t labelId) {
auto it = basicBlocks.find(labelId); auto it = basicBlocks.find(labelId);
if (it == basicBlocks.end()) { if (it == basicBlocks.end()) {

Просмотреть файл

@ -590,7 +590,8 @@ SPIRVEmitter::SPIRVEmitter(CompilerInstance &ci, EmitSPIRVOptions &options)
featureManager, options), featureManager, options),
entryFunctionId(0), curFunction(nullptr), curThis(0), entryFunctionId(0), curFunction(nullptr), curThis(0),
seenPushConstantAt(), isSpecConstantMode(false), seenPushConstantAt(), isSpecConstantMode(false),
foundNonUniformResourceIndex(false), needsLegalization(false) { foundNonUniformResourceIndex(false), needsLegalization(false),
mainSourceFileId(0) {
if (shaderModel.GetKind() == hlsl::ShaderModel::Kind::Invalid) if (shaderModel.GetKind() == hlsl::ShaderModel::Kind::Invalid)
emitError("unknown shader module: %0", {}) << shaderModel.GetName(); emitError("unknown shader module: %0", {}) << shaderModel.GetName();
@ -612,7 +613,8 @@ SPIRVEmitter::SPIRVEmitter(CompilerInstance &ci, EmitSPIRVOptions &options)
const auto &inputFiles = ci.getFrontendOpts().Inputs; const auto &inputFiles = ci.getFrontendOpts().Inputs;
if (options.enableDebugInfo && !inputFiles.empty()) { if (options.enableDebugInfo && !inputFiles.empty()) {
// File name // File name
theBuilder.setSourceFileName(theContext.takeNextId(), mainSourceFileId = theContext.takeNextId();
theBuilder.setSourceFileName(mainSourceFileId,
inputFiles.front().getFile().str()); inputFiles.front().getFile().str());
// Source code // Source code
@ -1484,6 +1486,7 @@ void SPIRVEmitter::doDoStmt(const DoStmt *theDoStmt,
theBuilder.setInsertPoint(continueBB); theBuilder.setInsertPoint(continueBB);
uint32_t condition = 0; uint32_t condition = 0;
if (const Expr *check = theDoStmt->getCond()) { if (const Expr *check = theDoStmt->getCond()) {
emitDebugLine(check->getLocStart());
condition = doExpr(check); condition = doExpr(check);
} else { } else {
condition = theBuilder.getConstantBool(true); condition = theBuilder.getConstantBool(true);
@ -1583,6 +1586,7 @@ void SPIRVEmitter::doWhileStmt(const WhileStmt *whileStmt,
uint32_t condition = 0; uint32_t condition = 0;
if (const Expr *check = whileStmt->getCond()) { if (const Expr *check = whileStmt->getCond()) {
emitDebugLine(check->getLocStart());
condition = doExpr(check); condition = doExpr(check);
} else { } else {
condition = theBuilder.getConstantBool(true); condition = theBuilder.getConstantBool(true);
@ -1674,6 +1678,7 @@ void SPIRVEmitter::doForStmt(const ForStmt *forStmt,
// Process the <init> block // Process the <init> block
if (const Stmt *initStmt = forStmt->getInit()) { if (const Stmt *initStmt = forStmt->getInit()) {
emitDebugLine(initStmt->getLocStart());
doStmt(initStmt); doStmt(initStmt);
} }
theBuilder.createBranch(checkBB); theBuilder.createBranch(checkBB);
@ -1683,6 +1688,7 @@ void SPIRVEmitter::doForStmt(const ForStmt *forStmt,
theBuilder.setInsertPoint(checkBB); theBuilder.setInsertPoint(checkBB);
uint32_t condition; uint32_t condition;
if (const Expr *check = forStmt->getCond()) { if (const Expr *check = forStmt->getCond()) {
emitDebugLine(check->getLocStart());
condition = doExpr(check); condition = doExpr(check);
} else { } else {
condition = theBuilder.getConstantBool(true); condition = theBuilder.getConstantBool(true);
@ -1711,6 +1717,7 @@ void SPIRVEmitter::doForStmt(const ForStmt *forStmt,
// Process the <continue> block // Process the <continue> block
theBuilder.setInsertPoint(continueBB); theBuilder.setInsertPoint(continueBB);
if (const Expr *cont = forStmt->getInc()) { if (const Expr *cont = forStmt->getInc()) {
emitDebugLine(cont->getLocStart());
doExpr(cont); doExpr(cont);
} }
theBuilder.createBranch(checkBB); // <continue> should jump back to header theBuilder.createBranch(checkBB); // <continue> should jump back to header
@ -1784,6 +1791,7 @@ void SPIRVEmitter::doIfStmt(const IfStmt *ifStmt,
if (const auto *declStmt = ifStmt->getConditionVariableDeclStmt()) if (const auto *declStmt = ifStmt->getConditionVariableDeclStmt())
doDeclStmt(declStmt); doDeclStmt(declStmt);
emitDebugLine(ifStmt->getCond()->getLocStart());
// First emit the instruction for evaluating the condition. // First emit the instruction for evaluating the condition.
const uint32_t condition = doExpr(ifStmt->getCond()); const uint32_t condition = doExpr(ifStmt->getCond());
@ -1986,6 +1994,8 @@ SpirvEvalInfo SPIRVEmitter::doBinaryOperator(const BinaryOperator *expr) {
} }
SpirvEvalInfo SPIRVEmitter::doCallExpr(const CallExpr *callExpr) { SpirvEvalInfo SPIRVEmitter::doCallExpr(const CallExpr *callExpr) {
emitDebugLine(callExpr->getLocStart());
if (const auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(callExpr)) if (const auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(callExpr))
return doCXXOperatorCallExpr(operatorCall); return doCXXOperatorCallExpr(operatorCall);
@ -9223,6 +9233,13 @@ void SPIRVEmitter::processPixelShaderAttributes(const FunctionDecl *decl) {
theBuilder.addExecutionMode(entryFunctionId, theBuilder.addExecutionMode(entryFunctionId,
spv::ExecutionMode::EarlyFragmentTests, {}); spv::ExecutionMode::EarlyFragmentTests, {});
} }
if (decl->getAttr<VKPostDepthCoverageAttr>()) {
theBuilder.addExtension(Extension::KHR_post_depth_coverage,
"[[vk::post_depth_coverage]]", decl->getLocation());
theBuilder.requireCapability(spv::Capability::SampleMaskPostDepthCoverage);
theBuilder.addExecutionMode(entryFunctionId,
spv::ExecutionMode::PostDepthCoverage, {});
}
} }
void SPIRVEmitter::processComputeShaderAttributes(const FunctionDecl *decl) { void SPIRVEmitter::processComputeShaderAttributes(const FunctionDecl *decl) {
@ -9950,5 +9967,13 @@ uint32_t SPIRVEmitter::extractVecFromVec4(uint32_t fromId,
} }
} }
void SPIRVEmitter::emitDebugLine(SourceLocation loc) {
if (spirvOptions.enableDebugInfo && mainSourceFileId != 0) {
auto floc = FullSourceLoc(loc, theCompilerInstance.getSourceManager());
theBuilder.debugLine(mainSourceFileId, floc.getSpellingLineNumber(),
floc.getSpellingColumnNumber());
}
}
} // end namespace spirv } // end namespace spirv
} // end namespace clang } // end namespace clang

Просмотреть файл

@ -873,6 +873,9 @@ private:
uint32_t constOffsets, uint32_t sample, uint32_t constOffsets, uint32_t sample,
uint32_t minLod, uint32_t residencyCodeId); uint32_t minLod, uint32_t residencyCodeId);
/// \brief Emit an OpLine instruction for the given source location.
void emitDebugLine(SourceLocation);
private: private:
/// \brief Wrapper method to create a fatal error message and report it /// \brief Wrapper method to create a fatal error message and report it
/// in the diagnostic engine associated with this consumer. /// in the diagnostic engine associated with this consumer.
@ -1017,6 +1020,9 @@ private:
/// This is the Patch Constant Function. This function is not explicitly /// This is the Patch Constant Function. This function is not explicitly
/// called from the entry point function. /// called from the entry point function.
FunctionDecl *patchConstFunc; FunctionDecl *patchConstFunc;
/// The <result-id> of the OpString containing the main source file's path.
uint32_t mainSourceFileId;
}; };
void SPIRVEmitter::doDeclStmt(const DeclStmt *declStmt) { void SPIRVEmitter::doDeclStmt(const DeclStmt *declStmt) {

Просмотреть файл

@ -10734,6 +10734,9 @@ void hlsl::HandleDeclAttributeForHLSL(Sema &S, Decl *D, const AttributeList &A,
declAttr = ::new (S.Context) VKConstantIdAttr(A.getRange(), S.Context, declAttr = ::new (S.Context) VKConstantIdAttr(A.getRange(), S.Context,
ValidateAttributeIntArg(S, A), A.getAttributeSpellingListIndex()); ValidateAttributeIntArg(S, A), A.getAttributeSpellingListIndex());
break; break;
case AttributeList::AT_VKPostDepthCoverage:
declAttr = ::new (S.Context) VKPostDepthCoverageAttr(A.getRange(), S.Context, A.getAttributeSpellingListIndex());
break;
default: default:
Handled = false; Handled = false;
return; return;

Просмотреть файл

@ -0,0 +1,17 @@
// RUN: %dxc /Tps_6_0 /Emain > %s | FileCheck %s
// CHECK: define void @main()
// CHECK: entry
float2 foo() {
return float2(1.0f, -1.0f);
}
[RootSignature("")]
float main() : SV_Target {
for (int c = 0; c < 2; ++c) {
if (foo()[c] >= 1.0f) {
return foo()[c];
}
}
return 1.0f;
}

Просмотреть файл

@ -0,0 +1,18 @@
// RUN: %dxc /Tps_6_0 /Emain > %s | FileCheck %s
// CHECK: define void @main()
// CHECK: entry
#define MAX_INDEX 5
groupshared float g_Array[2][(MAX_INDEX * MAX_INDEX)];
[RootSignature("")] float4 main(uint GroupIndex
: A) : SV_Target {
uint idx;
float l_Array[(MAX_INDEX * MAX_INDEX)] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
for (idx = 0; idx < (MAX_INDEX * MAX_INDEX); idx++) {
g_Array[GroupIndex][idx] = l_Array[idx];
}
return float4(g_Array[GroupIndex][0], g_Array[GroupIndex][1], g_Array[GroupIndex][2], g_Array[GroupIndex][3]);
}

Просмотреть файл

@ -0,0 +1,17 @@
// RUN: %dxc /Tps_6_0 /Emain > %s | FileCheck %s
// CHECK: define void @main()
// CHECK: entry
#define MAX_INDEX 14
groupshared float g_Array[2][(MAX_INDEX * MAX_INDEX)];
[RootSignature("")] float4 main(uint GroupIndex
: A) : SV_Target {
uint idx;
for (idx = 0; idx < (MAX_INDEX * MAX_INDEX); idx++) {
g_Array[GroupIndex][idx] = 0.0f;
}
return float4(g_Array[GroupIndex][0], g_Array[GroupIndex][1], g_Array[GroupIndex][2], g_Array[GroupIndex][3]);
}

Просмотреть файл

@ -0,0 +1,8 @@
// Run: %dxc -T ps_6_0 -E main
// CHECK: OpCapability SampleMaskPostDepthCoverage
// CHECK: OpExtension "SPV_KHR_post_depth_coverage"
// CHECK: OpExecutionMode %main PostDepthCoverage
[[vk::post_depth_coverage]]
float4 main() : SV_Target { return 1.0; }

Просмотреть файл

@ -0,0 +1,68 @@
// Run: %dxc -T ps_6_0 -E main -Zi
// CHECK: [[file:%\d+]] = OpString
// CHECK-SAME: spirv.debug.opline.hlsl
Texture2D MyTexture;
SamplerState MySampler;
uint foo(uint val) {
return val;
}
// Note that we do two passes for debuging info: first preprocessing and then
// compiling the preprocessed source code.
// Because the preprocessor prepends a "#line 1 ..." line to the whole file,
// the compliation sees line numbers incremented by 1.
float4 main(uint val : A) : SV_Target {
// CHECK: OpLine [[file]] 23 12
// CHECK-NEXT: OpLoad %uint %val
// CHECK-NEXT: OpBitReverse
uint a = reversebits(val);
// CHECK: OpLine [[file]] 27 12
// CHECK-NEXT: OpLoad %uint %a
uint b = foo(a);
// CHECK: OpLine [[file]] 31 14
// CHECK-NEXT: OpLoad %type_2d_image %MyTexture
float4 c = MyTexture.Sample(MySampler, float2(0.1, 0.2));
// CHECK: OpLine [[file]] 36 7
// CHECK-NEXT: OpLoad %uint %val
// CHECK-NEXT: OpUGreaterThan
if (val > 10) {
a = 5;
} else {
a = 6;
}
for (
// CHECK: OpLine [[file]] 45 7
// CHECK-NEXT: OpStore %b %uint_0
b = 0;
// CHECK: OpLine [[file]] 49 7
// CHECK-NEXT: OpLoad %uint %b
// CHECK-NEXT: OpULessThan
b < 10;
// CHECK: OpLine [[file]] 53 7
// CHECK-NEXT: OpLoad %uint %b
// CHECK-NEXT: OpIAdd
++b) {
a += 1;
}
// CHECK: OpLine [[file]] 60 10
// CHECK-NEXT: OpLoad %uint %b
// CHECK-NEXT: OpISub
while (--b > 0);
do {
c++;
// CHECK: OpLine [[file]] 66 12
// CHECK-NEXT: OpAccessChain %_ptr_Function_float %c %int_0
} while (c.x < 10);
return b * c;
}

Просмотреть файл

@ -0,0 +1,651 @@
// RUN: %clang_cc1 -HV 2015 -fsyntax-only -Wno-unused-value -ffreestanding -verify %s
float f_arr_empty_init[] = { 1, 2, 3 };
float f_arr_empty_pack[] = { 1, 2 ... }; // expected-error {{expansion is unsupported in HLSL}}
struct s_arr_i_f { int i; float f; };
s_arr_i_f arr_struct_none[] = { }; // TODO: this should fail - see comments in HLSLExternalSource::InitializeInitSequenceForHLSL
s_arr_i_f arr_struct_one[] = { 1, 2 };
s_arr_i_f arr_struct_incomplete[] = { 1, 2, 3 }; // expected-error {{too few elements in vector initialization (expected 4 elements, have 3)}}
s_arr_i_f arr_struct_two[] = { 1, 2, 3, 4 };
int g_int;
typeof(g_int) g_typeof_int; // expected-error {{HLSL requires a type specifier for all declarations}} expected-error {{expected ';' after top level declarator}} expected-error {{unknown type name 'typeof'; did you mean 'typedef'?}}
typedef int (*fn_int)(int); // expected-error {{pointers are unsupported in HLSL}}
auto g_auto = 3; // expected-error {{'auto' is a reserved keyword in HLSL}} expected-error {{HLSL requires a type specifier for all declarations}}
__is_signed g_is_signed; // expected-error {{'__is_signed' is a reserved keyword in HLSL}} expected-error {{HLSL requires a type specifier for all declarations}}
register int g_register; // expected-error {{'register' is a reserved keyword in HLSL}}
__thread int g_thread; // expected-error {{'__thread' is a reserved keyword in HLSL}}
thread_local int g_threadLocal; // expected-error {{expected unqualified-id}} expected-error {{unknown type name 'thread_local'}}
_Thread_local int g_Thread_local; // expected-error {{'_Thread_local' is a reserved keyword in HLSL}}
_Alignas(float) int g_Alignas; // expected-error {{'_Alignas' is a reserved keyword in HLSL}}
alignas(float) int g_alignas; // expected-error {{HLSL requires a type specifier for all declarations}} expected-error {{expected ';' after top level declarator}}
constexpr int g_constexpr = 3; // expected-error {{expected unqualified-id}} expected-error {{unknown type name 'constexpr'}}
friend int f_friend; // expected-error {{'friend' is a reserved keyword in HLSL}}
// Alternate numerics and builtin types.
short g_short; // expected-error {{'short' is a reserved keyword in HLSL}} expected-error {{HLSL requires a type specifier for all declarations}}
long g_long; // expected-error {{'long' is a reserved keyword in HLSL}} expected-error {{HLSL requires a type specifier for all declarations}}
signed int g_signed_int; // expected-error {{'signed' is a reserved keyword in HLSL}}
unsigned int g_unsigned_int;
char g_char; // expected-error {{'char' is a reserved keyword in HLSL}} expected-error {{HLSL requires a type specifier for all declarations}}
_Bool g_Bool; // expected-error {{unknown type name '_Bool'}}
_vector int altivec_vector; // expected-error {{expected unqualified-id}} expected-error {{unknown type name '_vector'}}
restrict int g_restrict; // expected-error {{expected unqualified-id}} expected-error {{unknown type name 'restrict'}}
__underlying_type(int) g_underlying_type; // expected-error {{__underlying_type is unsupported in HLSL}}
_Atomic(something) g_Atomic; // expected-error {{'_Atomic' is a reserved keyword in HLSL}} expected-error {{HLSL requires a type specifier for all declarations}}
typeof(g_int) g_anotherInt; // expected-error {{HLSL requires a type specifier for all declarations}} expected-error {{expected ';' after top level declarator}} expected-error {{unknown type name 'typeof'; did you mean 'typedef'?}}
// More GNU-specific keywords.
_Decimal32 g__Decimal32; // expected-error {{GNU decimal type extension not supported}}
_Decimal64 g__Decimal64; // expected-error {{GNU decimal type extension not supported}}
_Decimal128 g__Decimal128; // expected-error {{GNU decimal type extension not supported}}
__null g___null; // expected-error {{expected unqualified-id}}
__alignof g___alignof; // expected-error {{expected unqualified-id}}
__imag g___imag; // expected-error {{expected unqualified-id}}
__int128 g___int128; // expected-error {{'__int128' is a reserved keyword in HLSL}} expected-error {{HLSL requires a type specifier for all declarations}}
__label__ g___label; // expected-error {{expected unqualified-id}}
__real g___real; // expected-error {{expected unqualified-id}}
__FUNCTION__ g___FUNCTION; // expected-error {{expected unqualified-id}}
__PRETTY__ g___PRETTY; // expected-error {{unknown type name '__PRETTY__'}}
struct s_with_bitfield {
int f_bitfield : 3;
};
struct s_with_friend {
friend void some_fn(); // expected-error {{'friend' is a reserved keyword in HLSL}}
};
typedef int (*fn_int_const)(int) const; // expected-error {{expected ';' after top level declarator}} expected-error {{pointers are unsupported in HLSL}} expected-warning {{declaration does not declare anything}}
typedef int (*fn_int_volatile)(int) volatile; // expected-error {{expected ';' after top level declarator}} expected-error {{pointers are unsupported in HLSL}} expected-warning {{declaration does not declare anything}}
void fn_throw() throw() { } // expected-error {{exception specification is unsupported in HLSL}}
// This would otherwise be 'exception specification is unsupported in HLSL', but noexcept is not a keyword for HLSL.
void fn_noexcept() noexcept { }; // expected-error {{expected function body after function declarator}}
// This would be a failure because of unsupported trailer return types, but we mis-parse it differently.
auto fn_trailing() -> int { return 1; } ; // expected-error {{'auto' is a reserved keyword in HLSL}} expected-error {{expected function body after function declarator}}
void fn_param_with_default(int val = 1) { }
void fn_with_variadic(int a, ...) { } // expected-error {{variadic arguments is unsupported in HLSL}}
float f_arr_empty_uninit[]; // expected-error {{definition of variable with array type needs an explicit size or an initializer}}
float f_arr_static[static 3]; // expected-error {{static keyword on array derivation is unsupported in HLSL}}
float f_arr_star[*]; // expected-error {{definition of variable with array type needs an explicit size or an initializer}} expected-error {{variable-length array is unsupported in HLSL}}
#define <<(x) (x) // expected-error {{macro name must be an identifier}}
typedef int bool; // expected-error {{redeclaration of HLSL built-in type 'bool'}} expected-warning {{typedef requires a name}}
// This would generate an 'unknown pragma ignored' warning, but the default configuration ignores the warning.
#pragma align(4)
// Objective-C @ support for NSString literals.
const bool b = @"hello" != @"goodbye"; // expected-error {{expected expression}}
int fn_eq_default() = default; // expected-error {{'= default' is a function definition and must occur in a standalone declaration}}
typename typedef float4 TFloat4; // expected-error {{'typename' is a reserved keyword in HLSL}}
class C {
int fn_eq_default() = default; // expected-error {{function deletion and defaulting is unsupported in HLSL}}
// Errors are a bit misleading here, but ultimate we don't support these.
void* operator new(); // expected-error {{'operator' is a reserved keyword in HLSL}} expected-error {{pointers are unsupported in HLSL}}
void* operator new(int); // expected-error {{'operator' is a reserved keyword in HLSL}} expected-error {{pointers are unsupported in HLSL}}
void* operator new(size_t); // expected-error {{'operator' is a reserved keyword in HLSL}} expected-error {{pointers are unsupported in HLSL}}
C() = delete; // expected-error {{HLSL requires a type specifier for all declarations}} expected-error {{constructor cannot have a return type}}
};
asm ("int 3c"); // expected-error {{expected unqualified-id}}
@property int at_property_int; // expected-error {{expected unqualified-id}}
-int minus_int; // expected-error {{expected external declaration}}
static int static_int() { return 1; }
#import "foo.h" // expected-error {{invalid preprocessing directive}}
int knr_fn(f) int f; { return 1; } // expected-error {{expected ';' after top level declarator}} expected-error {{expected unqualified-id}} expected-error {{unknown type name 'f'}}
// TODO: this should be an error, but there is no C++ mention in any errors in any case;
// the only error case we would have cared to fix is for Objective C++
// [[attribute]] int g_value;
int is_supported() {
// GNU Extensions (in impl-reserved namespace)
//KEYWORD(_Decimal32, KEYALL)
//KEYWORD(_Decimal64, KEYALL)
//KEYWORD(_Decimal128, KEYALL)
//KEYWORD(__null, KEYCXX)
//KEYWORD(__alignof, KEYALL)
//KEYWORD(__attribute, KEYALL)
//KEYWORD(__builtin_choose_expr, KEYALL)
//KEYWORD(__builtin_offsetof, KEYALL)
if (__builtin_types_compatible_p(int, int)) return 1; // expected-error {{expected '(' for function-style cast or type construction}} expected-error {{expected '(' for function-style cast or type construction}}
//KEYWORD(__builtin_va_arg, KEYALL)
//KEYWORD(__extension__, KEYALL)
//KEYWORD(__imag, KEYALL)
//KEYWORD(__int128, KEYALL)
//KEYWORD(__label__, KEYALL)
//KEYWORD(__real, KEYALL)
//KEYWORD(__thread, KEYALL)
//KEYWORD(__FUNCTION__, KEYALL)
//KEYWORD(__PRETTY_FUNCTION__, KEYALL)
// GNU and MS Type Traits
if (__has_nothrow_assign(int)) return 1; // expected-error {{__has_nothrow_assign is unsupported in HLSL}}
if (__has_nothrow_move_assign(int)) return 1; // expected-error {{__has_nothrow_move_assign is unsupported in HLSL}}
if (__has_nothrow_copy(int)) return 1; // expected-error {{__has_nothrow_copy is unsupported in HLSL}}
if (__has_nothrow_constructor(int)) return 1; // expected-error {{__has_nothrow_constructor is unsupported in HLSL}}
if (__has_trivial_assign(int)) return 1; // expected-error {{__has_trivial_assign is unsupported in HLSL}}
if (__has_trivial_move_assign(int)) return 1; // expected-error {{__has_trivial_move_assign is unsupported in HLSL}}
if (__has_trivial_copy(int)) return 1; // expected-error {{__has_trivial_copy is unsupported in HLSL}}
if (__has_trivial_constructor(int)) return 1; // expected-error {{__has_trivial_constructor is unsupported in HLSL}}
if (__has_trivial_move_constructor(int)) return 1; // expected-error {{__has_trivial_move_constructor is unsupported in HLSL}}
if (__has_trivial_destructor(int)) return 1; // expected-error {{__has_trivial_destructor is unsupported in HLSL}}
if (__has_virtual_destructor(int)) return 1; // expected-error {{__has_virtual_destructor is unsupported in HLSL}}
if (__is_abstract(int)) return 1; // expected-error {{__is_abstract is unsupported in HLSL}}
if (__is_base_of(int, int)) return 1; // expected-error {{__is_base_of is unsupported in HLSL}}
if (__is_class(int)) return 1; // expected-error {{__is_class is unsupported in HLSL}}
if (__is_convertible_to(int, int)) return 1; // expected-error {{__is_convertible_to is unsupported in HLSL}}
if (__is_empty(int)) return 1; // expected-error {{__is_empty is unsupported in HLSL}}
if (__is_enum(int)) return 1; // expected-error {{__is_enum is unsupported in HLSL}}
if (__is_final(int)) return 1; // expected-error {{__is_final is unsupported in HLSL}}
if (__is_literal(int)) return 1; // expected-error {{__is_literal is unsupported in HLSL}}
if (__is_literal_type(int)) return 1; // expected-error {{__is_literal is unsupported in HLSL}}
if (__is_pod(int)) return 1; // expected-error {{__is_pod is unsupported in HLSL}}
if (__is_polymorphic(int)) return 1; // expected-error {{__is_polymorphic is unsupported in HLSL}}
if (__is_trivial(int)) return 1; // expected-error {{__is_trivial is unsupported in HLSL}}
if (__is_union(int)) return 1; // expected-error {{__is_union is unsupported in HLSL}}
// Clang-only C++ Type Traits
if (__is_trivially_constructible(int)) return 1; // expected-error {{__is_trivially_constructible is unsupported in HLSL}}
if (__is_trivially_copyable(int)) return 1; // expected-error {{__is_trivially_copyable is unsupported in HLSL}}
if (__is_trivially_assignable(int, int)) return 1; // expected-error {{__is_trivially_assignable is unsupported in HLSL}}
// Embarcadero Expression Traits
if (__is_lvalue_expr(1)) return 1; // expected-error {{__is_lvalue_expr is unsupported in HLSL}}
if (__is_rvalue_expr(1)) return 1; // expected-error {{__is_rvalue_expr is unsupported in HLSL}}
// Embarcadero Unary Type Traits
if (__is_arithmetic(int)) return 1; // expected-error {{__is_arithmetic is unsupported in HLSL}}
if (__is_floating_point(int)) return 1; // expected-error {{__is_floating_point is unsupported in HLSL}}
if (__is_integral(int)) return 1; // expected-error {{__is_integral is unsupported in HLSL}}
if (__is_complete_type(int)) return 1; // expected-error {{__is_complete_type is unsupported in HLSL}}
if (__is_void(int)) return 1; // expected-error {{__is_void is unsupported in HLSL}}
if (__is_array(int)) return 1; // expected-error {{__is_array is unsupported in HLSL}}
if (__is_function(int)) return 1; // expected-error {{__is_function is unsupported in HLSL}}
if (__is_reference(int)) return 1; // expected-error {{__is_reference is unsupported in HLSL}}
if (__is_lvalue_reference(int)) return 1; // expected-error {{__is_lvalue_reference is unsupported in HLSL}}
if (__is_rvalue_reference(int)) return 1; // expected-error {{__is_rvalue_reference is unsupported in HLSL}}
if (__is_fundamental(int)) return 1; // expected-error {{__is_fundamental is unsupported in HLSL}}
if (__is_object(int)) return 1; // expected-error {{__is_object is unsupported in HLSL}}
if (__is_scalar(int)) return 1; // expected-error {{__is_scalar is unsupported in HLSL}}
if (__is_compound(int)) return 1; // expected-error {{__is_compound is unsupported in HLSL}}
if (__is_pointer(int)) return 1; // expected-error {{__is_pointer is unsupported in HLSL}}
if (__is_member_object_pointer(int)) return 1; // expected-error {{__is_member_object_pointer is unsupported in HLSL}}
if (__is_member_function_pointer(int)) return 1; // expected-error {{__is_member_function_pointer is unsupported in HLSL}}
if (__is_member_pointer(int)) return 1; // expected-error {{__is_member_pointer is unsupported in HLSL}}
if (__is_const(int)) return 1; // expected-error {{__is_const is unsupported in HLSL}}
if (__is_volatile(int)) return 1; // expected-error {{__is_volatile is unsupported in HLSL}}
if (__is_standard_layout(int)) return 1; // expected-error {{__is_standard_layout is unsupported in HLSL}}
if (__is_signed(int)) return 1; // expected-error {{__is_signed is unsupported in HLSL}}
if (__is_unsigned(int)) return 1; // expected-error {{__is_unsigned is unsupported in HLSL}}
// Embarcadero Binary Type Traits
if (__is_same(int, int)) return 1; // expected-error {{__is_same is unsupported in HLSL}}
if (__is_convertible(int, int)) return 1; // expected-error {{__is_convertible is unsupported in HLSL}}
if (__array_rank(int, 1)) return 1; // expected-error {{__array_rank is unsupported in HLSL}}
if (__array_extent(int, 1)) return 1; // expected-error {{__array_extent is unsupported in HLSL}}
__attribute__((common)) int i; // expected-error {{attribute annotations are unsupported in HLSL}}
return 0;
}
[availability(*, unavailable, renamed="somethingelse")] void fn_unavailable(); // expected-error {{'availability' is unsupported in HLSL}}
__declspec(align(16)) struct SAligned { int i; }; // expected-error {{'__declspec' is a reserved keyword in HLSL}}
void __fastcall fn_fastcall(); // expected-error {{'__fastcall' is a reserved keyword in HLSL}}
// These aren't even recognized as keywords.
int _pascal fn_pascal(); // expected-error {{expected ';' after top level declarator}}
int _kernel fn_kernel(); // expected-error {{expected ';' after top level declarator}}
int __private int__private; // expected-error {{expected ';' after top level declarator}}
int __global int__global; // expected-error {{expected ';' after top level declarator}}
int __local int__local; // expected-error {{expected ';' after top level declarator}}
int __constant int__constant; // expected-error {{expected ';' after top level declarator}}
int global intglobal; // expected-error {{expected ';' after top level declarator}}
int local intlocal; // expected-error {{expected ';' after top level declarator}}
int constant intconstant; // expected-error {{expected ';' after top level declarator}}
#ifdef __cplusplus
// HLSL is different enough from C++ that this should be false.
#error __cplusplus is defined
#endif
typedef void VOID_TYPE;
template <typename T> // expected-error {{'template' is a reserved keyword in HLSL}}
int fn_template(T t)
{
return (int)t;
}
int template; // expected-error {{'template' is a reserved keyword in HLSL}} expected-error {{expected unqualified-id}}
int get_value(VOID_TYPE) {
return 1;
}
extern "C" int get_value(int) { // expected-error {{expected unqualified-id}}
return 2;
}
void vla(int size) {
int n[size]; // expected-error {{variable length arrays are not supported in HLSL}}
return n[0];
}
enum MyEnum { MyEnum_MyVal1, MyEnum_MyVal2 }; // /* expected-error {{enum is unsupported in HLSL before 2017}} expected-warning {{declaration does not declare anything}} */
enum class MyEnumWithClass { MyEnumWithClass_MyVal1, MyEnumWithClass_MyVal2 }; // /* expected-error {{enum is unsupported in HLSL before 2017}} expected-warning {{declaration does not declare anything}} */
float4 fn_with_semantic() : SV_Target0{
return 0;
}
float4 fn_with_semantic_arg(float4 arg : SV_SOMETHING) : SV_Target0{
return arg;
}
int fn_with_try_body()
try // expected-error {{expected function body after function declarator}}
{
return 1;
}
// unnamed namespace definition.
namespace { // expected-error {{expected identifier}}
int f_anon_ns_int;
}
// original namespace definition.
namespace MyNS {
}
namespace MyNs::Nested { // expected-error {{nested namespace definition must define each namespace separately}}
}
// original namespace definition with inline.
inline namespace MyInlineNs { // expected-error {{expected unqualified-id}}
}
// extension namespace definition.
namespace MyNs {
int my_ns_extension;
}
// namespace alias definition.
namespace NamespaceAlias = MyNs; // expected-error {{expected identifier}}
using MyNS; // expected-error {{'using' is a reserved keyword in HLSL}}
int using; // expected-error {{'using' is a reserved keyword in HLSL}}
struct my_struct { };
class my_class { };
interface my_interface { };
class my_class_2 : my_class { };
class my_class_3 : my_interface { };
class my_class_4 : my_struct { };
struct my_struct_2 : my_struct { };
struct my_struct_3 : my_class { };
struct my_struct_4 : my_interface { };
struct my_struct_5 : my_class, my_interface { };
struct my_struct_6 : my_class, my_interface, my_struct { }; // expected-error {{multiple concrete base types specified}}
interface my_interface_2 : my_interface { }; // expected-error {{interfaces cannot inherit from other types}}
class my_class_public : public my_class { }; // expected-error {{base type access specifier is unsupported in HLSL}}
struct forward_struct; // this fails in fxc, but we allow it now /* expected-error {{struct declaration without definition is unsupported in HLSL}} */
struct my_struct_type_decl { int a; } my_struct_var_decl;
struct my_struct_type_decl_parens { int a; } (my_struct_var_decl_parens); // expected-error {{HLSL requires a type specifier for all declarations}} expected-error {{expected ';' after struct}}
struct my_struct_type_const { int a; } const my_struct_type_var; // // expected-error {{HLSL requires a type specifier for all declarations}} expected-error {{expected ';' after struct}}
struct my_struct_type_init { int a; } my_struct_type_init_one = { 1 }, my_struct_type_init_two = { 2 };
struct my_struct_type_static { int a; } static my_struct_type_static; // expected-error {{expected ';' after struct}} expected-warning {{declaration does not declare anything}}
struct { int my_anon_struct_field; } my_anon_struct_type;
void fn_my_struct_type_decl() {
my_struct_type_decl local_var;
}
struct s_with_template_member {
template<typename T> T fn(); // expected-error {{'template' is a reserved keyword in HLSL}}
};
struct s_with_using {
using MyNS; // expected-error {{'using' is a reserved keyword in HLSL}}
};
struct s_with_init {
int i = 1; // expected-error {{struct/class members cannot have default values}}
};
struct s_with_multiple {
int i, j;
};
class c_outer {
struct { int allowed; };
struct c_inner { int disallowed; }; // expected-error {{nested named class/struct/interfaces are not supported in HLSL}}
};
class c_outer_typedef {
typedef int local_int; // expected-error {{nested typedefs are not supported in HLSL}}
};
class c_outer_fn {
int fn() {
class local_class { int j; };
typedef int local_int;
}
};
class c_public {
public: int i; // expected-error {{'public' is a reserved keyword in HLSL}}
};
namespace ns_with_struct {
struct s { int i; };
}
matrix<int...> g_matrix_pack; // expected-error {{ellipsis is unsupported in HLSL}}
matrix<ns_with_struct::s> g_matrix_ns; // expected-error {{'ns_with_struct::s' cannot be used as a type parameter where a scalar is required}}
matrix<int, 1, 2> g_matrix_simple;
matrix<s_with_multiple, 1, 2> g_matrix_user; // expected-error {{'s_with_multiple' cannot be used as a type parameter where a scalar is required}}
matrix<float2, 1, 1> g_matrix_vector_shorthand; // expected-error {{'float2' cannot be used as a type parameter where a scalar is required}}
matrix<template matrix<typename, 1, 2> > g_matrix_template_template; // expected-error {{expected expression}} expected-error {{expected unqualified-id}}
matrix<matrix<typename, 1, 2> > g_matrix_template_template_nokw; // expected-error {{expected a qualified name after 'typename'}} expected-error {{expected a type}} expected-error {{expected a type}}
matrix<matrix<float, 1, 2> ... > g_matrix_template_template_ellipsis; // expected-error {{ellipsis is unsupported in HLSL}}
#pragma unknown
int global_fn() { return 1; }
void fn_int_arg(int);
void statements()
{
int local_i = 1; // expected-note {{declared here}}
// attempt to parse a label.
my_label: local_i = 1; // expected-error {{label is unsupported in HLSL}}
// attempt to parse an obj-c statement
@throw local_i; // expected-error {{expected expression}}
// verify that compound statement blocks have their own scope
{
// inner block with scope
float local_f;
}
{
// inner block with scope
double local_f;
}
// verify that GNU local label (__label__) is disallowed
{
__label__ X, Y; // expected-error {{local label is unsupported in HLSL}}
}
// expression statements
(void)local_i; // disallowed in fxc as the cast is impossible, but allowed for compat now
local_i;
if (local_i == 0) {
local_i++;
}
if (int my_if_local = global_fn()) { // this is an addition to fxc HLSL
local_i++;
my_if_local++;
} else {
my_if_local--;
}
// declaration in 'if' conditional clause does not leak out
my_if_local++; // expected-error {{use of undeclared identifier 'my_if_local'}}
switch (int my_switch_local = global_fn()) {
case 0: my_switch_local--; return;
}
while (int my_while_local = global_fn()) {
my_while_local--;
}
switch(local_i) {
case 0:
local_i = 2;
break;
case 1 + 2:
local_i = 3;
break;
case local_i: // expected-error {{expression is not an integral constant expression}} expected-note {{read of non-const variable 'local_i' is not allowed in a constant expression}}
break;
case 10 ... 12: // expected-error {{case range is unsupported in HLSL}}
break;
default:
local_i = 100;
// fall through
}
while (local_i > 0) {
local_i -= 1;
if (local_i == 1) continue;
if (local_i == 2) break;
}
asm(); // expected-error {{'asm' is a reserved keyword in HLSL}}
try { // expected-error {{'try' is a reserved keyword in HLSL}}
local_i = 1;
} catch(...) {
local_i = 2;
}
// do/while (without braces)
do local_i += 1; while (local_i < 3);
// for, leaking declaration from control part
for (int i = 0; i < 10; ++i) {
local_i = i;
break;
}
local_i = i - 1;
// for, not leaking declaration from body
for (int val = 0; i < 10; ++i) {
int val_inner = val;
break;
}
local_i = val_inner; // expected-error {{use of undeclared identifier 'val_inner'}}
// for, redeclaring local
int red_same; // expected-note {{previous definition is here}}
for (int red_same = 0;;) break; // expected-warning {{redefinition of 'red_same' shadows declaration in the outer scope; most recent declaration will be used}}
// for, redeclaring local with different type
int red_different; // expected-note {{previous definition is here}}
for (float red_different = 0;;) break; // expected-warning {{redefinition of 'red_different' with a different type: 'float' vs 'int' shadows declaration in the outer scope; most recent declaration will be used}}
// this proves that the more recent variable is in scope
int2 red_i_then_int = 0; // expected-note {{previous definition is here}}
for (int red_i_then_int = 0;;) break; //expected-warning {{redefinition of 'red_i_then_int' with a different type: 'int' vs 'int2' shadows declaration in the outer scope; most recent declaration will be used}}
fn_int_arg(red_i_then_int);
fn_int_arg(int2(0,0)); // int2 to int conversion is allowed // expected-warning {{implicit truncation of vector type}}
// for without declaration
for (local_i = 0; ;) {
break;
}
// for without initialization
for (int j;;) { break; }
// ranged for is disallowed
for (int n : local_i) { // expected-error {{expected ';' in 'for' statement specifier}} expected-error {{expected ';' in 'for' statement specifier}} expected-error {{semantic is not a valid modifier for a local variable}}
break;
}
for (int n_again in local_i) { // expected-error {{expected ';' in 'for' statement specifier}} expected-error {{expected unqualified-id}} expected-error {{unknown type name 'local_i'}} expected-error {{variable declaration in condition must have an initializer}}
}
// if/else
if (local_i == 0)
local_i = 1;
else {
local_i = 2;
}
// empty/null statements
;;;
switch (local_i) {
default: // expected-error {{label at end of compound statement: expected statement}}
}
// goto statement
goto my_label; // expected-error {{goto is unsupported in HLSL}}
// return statement
return;
// discard statement
discard;
}
void expressions()
{
int local_i;
local_i = 1 > 2 ? 0 : 1;
// GNU extension to ternary operator, missing second argument to mean first
local_i = 1 > 2 ? : 1; // expected-error {{use of GNU ?: conditional expression extension, omitting middle operand is unsupported in HLSL}}
// initializer lists as right-hand in binary operator (err_init_list_bin_op), but HLSL does not support init lists here
local_i = 1 + 2 * { 1 }; // expected-error {{expected expression}}
local_i = true;
local_i = __objc_no; // expected-error {{'__objc_no' is a reserved keyword in HLSL}}
local_i = __objc_yes; // expected-error {{'__objc_yes' is a reserved keyword in HLSL}}
local_i = nullptr; // expected-error {{use of undeclared identifier 'nullptr'}}
local_i = decltype(1)(1); // expected-error {{use of undeclared identifier 'decltype'}}
local_i = __is_integral(bool); // expected-error {{__is_integral is unsupported in HLSL}}
local_i = &local_i; // expected-error {{operator is not supported}}
local_i = 'c'; // this is fine
local_i = '\xFF'; // this is fine
local_i = 'ab'; // expected-error {{unsupported style of char literal - use a single-character char-based literal}} expected-warning {{multi-character character constant}}
local_i = L'a'; // expected-error {{non-ASCII/multiple-char character constant is unsupported in HLSL}}
local_i = L"AB"; // expected-error {{non-ASCII string constant is unsupported in HLSL}}
local_i = __FUNCTION__; // expected-error {{'__FUNCTION__' is a reserved keyword in HLSL}}
local_i = _Generic('a',default:0); // expected-error {{'_Generic' is a reserved keyword in HLSL}}
// for string literals, see string.hlsl
local_i = *local_i; // expected-error {{operator is not supported}}
local_i = +local_i;
local_i = -local_i;
local_i = ~local_i;
local_i = !local_i;
local_i = __real local_i; // expected-error {{'__real' is a reserved keyword in HLSL}}
local_i = __imag local_i; // expected-error {{'__imag' is a reserved keyword in HLSL}}
local_i = typeid 123; // expected-error {{'typeid' is a reserved keyword in HLSL}}
local_i = __uuidof(local_i); // expected-error {{use of undeclared identifier '__uuidof'}}
struct CInternal {
int i;
int fn() { return this.i; }
CInternal getSelf() { return this; }
int operator+(int); // expected-error {{'operator' is a reserved keyword in HLSL}}
};
if (__is_pod(int)) { } // expected-error {{__is_pod is unsupported in HLSL}}
^(int x){ return x + 1; }; // expected-error {{block is unsupported in HLSL}} expected-error {{compound literal is unsupported in HLSL}} expected-error {{expected ')'}} expected-note {{to match this '('}}
CInternal internal;
internal->fn(); // expected-error {{operator is not supported}}
local_i = (int3) { 1, 2, 3 }; // expected-error {{compound literal is unsupported in HLSL}}
Texture2D<::c_outer_fn> local_texture; // expected-error {{'::c_outer_fn' cannot be used as a type parameter}}
::new local_new; // expected-error {{new' is a reserved keyword in HLSL}}
::template foo local_template; // expected-error {{'template' is a reserved keyword in HLSL}} expected-error {{unknown type name 'foo'}}
class CInlineWithTry {
void fn()
try // expected-error {{expected function body after function declarator}}
{
int n;
}
catch(...)
{
}
void fn_other()
try // expected-error {{expected function body after function declarator}}
{
return;
}
int local_field_1 = 1; // expected-error {{struct/class members cannot have default values}}
int local_field_2[] = { 1 }; // expected-error {{array bound cannot be deduced from an in-class initializer}} expected-error {{array dimensions of struct/class members must be explicit}} expected-error {{struct/class members cannot have default values}}
};
}
// Pragmas.
// TODO: unhandled pragmas should result in a warning
int unused_i;
#pragma unused(unused_i)
#pragma unknown
#pragma GCC visibility push(public)
#pragma pack(push, 1)
#pragma ms_struct(on)
#pragma comment(lib, "kernel32.lib")
#pragma align 64
#pragma weak expressions
#pragma weak expressions = expressions
#pragma redefine_extname g_int new_name_g_int
#pragma STDC FP_CONTRACT on
#pragma OPENCL EXTENSION
#pragma clang __debug captured
#pragma
// Preprocessor directives.
#define A_DEFINE 1
#if (A_DEFINE==1)
#elif (A_DEFINE==2)
#else
#warning it does not work
#endif
// Verified this works but it trips the error processor.
// #error err
#ifdef A_DEFINE
#endif
#undef A_DEFINE
#ifndef A_DEFINE
#else
#error it does not work
#endif
#line 321
int;
// expected-warning@321 {{declaration does not declare anything}}
float4 plain(float4 param4 /* : FOO */) /*: FOO */{
int i[0]; // expected-error {{array dimension must be between 1 and 65536}}
const j; // expected-error {{HLSL requires a type specifier for all declarations}}
long long ll; // expected-error {{'long' is a reserved keyword in HLSL}} expected-error {{'long' is a reserved keyword in HLSL}} expected-error {{HLSL requires a type specifier for all declarations}}
return is_supported();
}

Просмотреть файл

@ -251,8 +251,8 @@ void vla(int size) {
return n[0]; return n[0];
} }
enum MyEnum { MyEnum_MyVal1, MyEnum_MyVal2 }; // enum MyEnum { MyEnum_MyVal1, MyEnum_MyVal2 };
enum class MyEnumWithClass { MyEnumWithClass_MyVal1, MyEnumWithClass_MyVal2 }; // enum class MyEnumWithClass { MyEnumWithClass_MyVal1, MyEnumWithClass_MyVal2 };
float4 fn_with_semantic() : SV_Target0{ float4 fn_with_semantic() : SV_Target0{
return 0; return 0;
@ -348,7 +348,8 @@ struct s_with_multiple {
}; };
class c_outer { class c_outer {
class c_inner { int disallowed; }; // expected-error {{nested class is unsupported in HLSL}} struct { int allowed; };
struct c_inner { int allowed_HV2016; };
}; };
class c_outer_typedef { class c_outer_typedef {
@ -596,7 +597,7 @@ void expressions()
} }
int local_field_1 = 1; // expected-error {{struct/class members cannot have default values}} int local_field_1 = 1; // expected-error {{struct/class members cannot have default values}}
int local_field_2[] = { 1 }; // expected-error {{array dimensions of struct/class members must be explicit}} expected-error {{array bound cannot be deduced from an in-class initializer}} expected-error {{struct/class members cannot have default values}} int local_field_2[] = { 1 }; // expected-error {{array bound cannot be deduced from an in-class initializer}} expected-error {{array dimensions of struct/class members must be explicit}} expected-error {{struct/class members cannot have default values}}
}; };
} }

Просмотреть файл

@ -41,6 +41,7 @@ public:
TEST_METHOD(RunConstAssign) TEST_METHOD(RunConstAssign)
TEST_METHOD(RunConstDefault) TEST_METHOD(RunConstDefault)
TEST_METHOD(RunCppErrors) TEST_METHOD(RunCppErrors)
TEST_METHOD(RunCppErrorsHV2015)
TEST_METHOD(RunCXX11Attributes) TEST_METHOD(RunCXX11Attributes)
TEST_METHOD(RunEnums) TEST_METHOD(RunEnums)
TEST_METHOD(RunFunctions) TEST_METHOD(RunFunctions)
@ -152,6 +153,10 @@ TEST_F(VerifierTest, RunCppErrors) {
CheckVerifiesHLSL(L"cpp-errors.hlsl"); CheckVerifiesHLSL(L"cpp-errors.hlsl");
} }
TEST_F(VerifierTest, RunCppErrorsHV2015) {
CheckVerifiesHLSL(L"cpp-errors-hv2015.hlsl");
}
TEST_F(VerifierTest, RunCXX11Attributes) { TEST_F(VerifierTest, RunCXX11Attributes) {
CheckVerifiesHLSL(L"cxx11-attributes.hlsl"); CheckVerifiesHLSL(L"cxx11-attributes.hlsl");
} }

Просмотреть файл

@ -1008,6 +1008,9 @@ TEST_F(FileTest, IntrinsicsNonUniformResourceIndex) {
TEST_F(FileTest, AttributeEarlyDepthStencil) { TEST_F(FileTest, AttributeEarlyDepthStencil) {
runFileTest("attribute.earlydepthstencil.ps.hlsl"); runFileTest("attribute.earlydepthstencil.ps.hlsl");
} }
TEST_F(FileTest, AttributePostDepthCoverage) {
runFileTest("attribute.postdepthcoverage.ps.hlsl");
}
TEST_F(FileTest, AttributeNumThreads) { TEST_F(FileTest, AttributeNumThreads) {
runFileTest("attribute.numthreads.hlsl"); runFileTest("attribute.numthreads.hlsl");
} }
@ -1315,6 +1318,10 @@ TEST_F(FileTest, SpirvDebugOpSource) {
runFileTest("spirv.debug.opsource.hlsl"); runFileTest("spirv.debug.opsource.hlsl");
} }
TEST_F(FileTest, SpirvDebugOpLine) {
runFileTest("spirv.debug.opline.hlsl");
}
TEST_F(FileTest, VulkanAttributeErrors) { TEST_F(FileTest, VulkanAttributeErrors) {
runFileTest("vk.attribute.error.hlsl", Expect::Failure); runFileTest("vk.attribute.error.hlsl", Expect::Failure);
} }