Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ line upon naming the release. Refer to previous for appropriate section names.
- The `shared` and `uniform` keywords are removed in HLSL 202x, with
compatibility warnings available for earlier language versions
[#8482](https://github.com/microsoft/DirectXShaderCompiler/issues/8482).
- HLSL 202x now supports variadic templates and template function parameter
packs, pack expansions, and `sizeof...()`
[#8905](https://github.com/microsoft/DirectXShaderCompiler/issues/8905).

#### SPIR-V

Expand Down
5 changes: 4 additions & 1 deletion tools/clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -816,5 +816,8 @@ def HLSL2026Compat
HLSL2026RemovedKeywords]>;

def HLSLGroupshared202x : DiagGroup<"hlsl-groupshared-202x">;
def HLSL202xExtensions : DiagGroup<"hlsl-202x-extensions", [HLSLGroupshared202x]>;
def HLSLFoldExpressions : DiagGroup<"hlsl-fold-expressions">;
def HLSL202xExtensions
: DiagGroup<"hlsl-202x-extensions", [HLSLFoldExpressions,
HLSLGroupshared202x]>;
// HLSL Change Ends
4 changes: 4 additions & 0 deletions tools/clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,10 @@ def warn_cxx98_compat_generalized_initializer_lists : Warning<
InGroup<CXX98Compat>, DefaultIgnore;
def err_hlsl_compat_generalized_initializer_lists : Error<
"generalized initializer lists are incompatible with HLSL">;
def warn_hlsl_fold_expression
: Warning<"fold expressions are a C++17 extension and are not part of "
"standard HLSL">,
InGroup<HLSLFoldExpressions>;
def err_init_list_bin_op : Error<"initializer list cannot be used on the "
"%select{left|right}0 hand side of operator '%1'">;
def warn_cxx98_compat_trailing_return_type : Warning<
Expand Down
7 changes: 7 additions & 0 deletions tools/clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,13 @@ class LangOptions : public LangOptionsBase {
return MSCompatibilityVersion >= MajorVersion * 10000000U;
}

// HLSL Change Starts
/// Whether the active HLSL version rejects variadic templates.
bool HLSLDisallowsVariadicTemplates() const {
Comment thread
llvm-beanz marked this conversation as resolved.
return HLSL && HLSLVersion < hlsl::LangStd::v202x;
}
// HLSL Change Ends

/// \brief Reset all of the options that are not considered when building a
/// module.
void resetNonModularOptions();
Expand Down
2 changes: 2 additions & 0 deletions tools/clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3078,6 +3078,8 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
const FunctionProtoType::ExtProtoInfo &EPI,
ArrayRef<hlsl::ParameterModifier> ParamMods) const { // HLSL Change - param mods
size_t NumArgs = ArgArray.size();
assert((ParamMods.empty() || ParamMods.size() == NumArgs) &&
"parameter modifier count does not match parameter count");

// Unique functions, to guarantee there is only one function of a particular
// structure.
Expand Down
20 changes: 14 additions & 6 deletions tools/clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2370,15 +2370,23 @@ unsigned ParmVarDecl::getParameterIndexLarge() const {

// HLSL Change Begins
void ParmVarDecl::updateOutParamToRefType(ASTContext &C) {
QualType ParamType = getType();
const PackExpansionType *Expansion = dyn_cast<PackExpansionType>(ParamType);
if (Expansion)
ParamType = Expansion->getPattern();

// Aggregate type will be indirect param convert to pointer type.
// So don't update to ReferenceType.
if ((!getType()->isArrayType() && !getType()->isRecordType()) ||
hlsl::IsHLSLVecMatType(getType()))
setType(C.getLValueReferenceType(getType(), false));
if ((!ParamType->isArrayType() && !ParamType->isRecordType()) ||
hlsl::IsHLSLVecMatType(ParamType))
ParamType = C.getLValueReferenceType(ParamType, false);
// Add restrict to out param.
QualType QT = getType();
QT.addRestrict();
setType(QT);
ParamType.addRestrict();

if (Expansion)
ParamType =
C.getPackExpansionType(ParamType, Expansion->getNumExpansions());
setType(ParamType);
}
// HLSL Change Ends

Expand Down
2 changes: 2 additions & 0 deletions tools/clang/lib/Frontend/InitPreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,8 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
// HLSL Version
Builder.defineMacro("__HLSL_VERSION",
Twine((unsigned int)LangOpts.HLSLVersion));
if (!LangOpts.HLSLDisallowsVariadicTemplates())
Builder.defineMacro("__cpp_variadic_templates", "200704");
// This define is enabled in Clang and allows conditionally compiling code
// based on whether or not native 16-bit types are supported.
if (!LangOpts.UseMinPrecision)
Expand Down
53 changes: 28 additions & 25 deletions tools/clang/lib/Lex/PPMacroExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1156,7 +1156,9 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("cxx_unicode_literals", LangOpts.CPlusPlus11)
.Case("cxx_unrestricted_unions", LangOpts.CPlusPlus11)
.Case("cxx_user_literals", LangOpts.CPlusPlus11)
.Case("cxx_variadic_templates", LangOpts.CPlusPlus11)
.Case("cxx_variadic_templates",
LangOpts.CPlusPlus11 ||
(LangOpts.HLSL && !LangOpts.HLSLDisallowsVariadicTemplates()))
// C++1y features
.Case("cxx_aggregate_nsdmi", LangOpts.CPlusPlus14)
.Case("cxx_binary_literals", LangOpts.CPlusPlus14)
Expand Down Expand Up @@ -1231,30 +1233,31 @@ static bool HasExtension(const Preprocessor &PP, const IdentifierInfo *II) {
// Because we inherit the feature list from HasFeature, this string switch
// must be less restrictive than HasFeature's.
return llvm::StringSwitch<bool>(Extension)
// C11 features supported by other languages as extensions.
.Case("c_alignas", true)
.Case("c_alignof", true)
.Case("c_atomic", true)
.Case("c_generic_selections", true)
.Case("c_static_assert", true)
.Case("c_thread_local", PP.getTargetInfo().isTLSSupported())
// C++11 features supported by other languages as extensions.
.Case("cxx_atomic", LangOpts.CPlusPlus)
.Case("cxx_deleted_functions", LangOpts.CPlusPlus)
.Case("cxx_explicit_conversions", LangOpts.CPlusPlus)
.Case("cxx_inline_namespaces", LangOpts.CPlusPlus)
.Case("cxx_local_type_template_args", LangOpts.CPlusPlus)
.Case("cxx_nonstatic_member_init", LangOpts.CPlusPlus)
.Case("cxx_override_control", LangOpts.CPlusPlus)
.Case("cxx_range_for", LangOpts.CPlusPlus)
.Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus)
.Case("cxx_rvalue_references", LangOpts.CPlusPlus)
.Case("cxx_variadic_templates", LangOpts.CPlusPlus)
// C++1y features supported by other languages as extensions.
.Case("cxx_binary_literals", true)
.Case("cxx_init_captures", LangOpts.CPlusPlus11)
.Case("cxx_variable_templates", LangOpts.CPlusPlus)
.Default(false);
// C11 features supported by other languages as extensions.
.Case("c_alignas", true)
.Case("c_alignof", true)
.Case("c_atomic", true)
.Case("c_generic_selections", true)
.Case("c_static_assert", true)
.Case("c_thread_local", PP.getTargetInfo().isTLSSupported())
// C++11 features supported by other languages as extensions.
.Case("cxx_atomic", LangOpts.CPlusPlus)
.Case("cxx_deleted_functions", LangOpts.CPlusPlus)
.Case("cxx_explicit_conversions", LangOpts.CPlusPlus)
.Case("cxx_inline_namespaces", LangOpts.CPlusPlus)
.Case("cxx_local_type_template_args", LangOpts.CPlusPlus)
.Case("cxx_nonstatic_member_init", LangOpts.CPlusPlus)
.Case("cxx_override_control", LangOpts.CPlusPlus)
.Case("cxx_range_for", LangOpts.CPlusPlus)
.Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus)
.Case("cxx_rvalue_references", LangOpts.CPlusPlus)
.Case("cxx_variadic_templates",
LangOpts.CPlusPlus && !LangOpts.HLSLDisallowsVariadicTemplates())
// C++1y features supported by other languages as extensions.
.Case("cxx_binary_literals", true)
.Case("cxx_init_captures", LangOpts.CPlusPlus11)
.Case("cxx_variable_templates", LangOpts.CPlusPlus)
.Default(false);
}

/// EvaluateHasIncludeCommon - Process a '__has_include("path")'
Expand Down
5 changes: 2 additions & 3 deletions tools/clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6109,12 +6109,11 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// been expanded or contains auto; otherwise, it is parsed as part of the
// parameter-declaration-clause.
if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&
!getLangOpts().HLSL && // HLSL Change: do not support ellipsis
!getLangOpts().HLSLDisallowsVariadicTemplates() && // HLSL Change
!((D.getContext() == Declarator::PrototypeContext ||
D.getContext() == Declarator::LambdaExprParameterContext ||
D.getContext() == Declarator::BlockLiteralContext) &&
NextToken().is(tok::r_paren) &&
!D.hasGroupingParens() &&
NextToken().is(tok::r_paren) && !D.hasGroupingParens() &&
!Actions.containsUnexpandedParameterPacks(D) &&
D.getDeclSpec().getTypeSpecType() != TST_auto)) {
SourceLocation EllipsisLoc = ConsumeToken();
Expand Down
14 changes: 9 additions & 5 deletions tools/clang/lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1946,7 +1946,8 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
ConsumeToken();

// [C++11] 'sizeof' '...' '(' identifier ')'
if (Tok.is(tok::ellipsis) && OpTok.is(tok::kw_sizeof) && !getLangOpts().HLSL) { // HLSL Change
if (Tok.is(tok::ellipsis) && OpTok.is(tok::kw_sizeof) &&
!getLangOpts().HLSLDisallowsVariadicTemplates()) { // HLSL Change
SourceLocation EllipsisLoc = ConsumeToken();
SourceLocation LParenLoc, RParenLoc;
IdentifierInfo *Name = nullptr;
Expand Down Expand Up @@ -2747,9 +2748,12 @@ ExprResult Parser::ParseFoldExpression(ExprResult LHS,
}
}

Diag(EllipsisLoc, getLangOpts().CPlusPlus1z
? diag::warn_cxx14_compat_fold_expression
: diag::ext_fold_expression);
if (getLangOpts().HLSL && !getLangOpts().HLSLDisallowsVariadicTemplates())
Diag(EllipsisLoc, diag::warn_hlsl_fold_expression);
else
Diag(EllipsisLoc, getLangOpts().CPlusPlus1z
? diag::warn_cxx14_compat_fold_expression
: diag::ext_fold_expression);

T.consumeClose();
return Actions.ActOnCXXFoldExpr(T.getOpenLocation(), LHS.get(), Kind,
Expand Down Expand Up @@ -2801,7 +2805,7 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,

if (Tok.is(tok::ellipsis)) {
// HLSL Change Starts
if (getLangOpts().HLSL) {
if (getLangOpts().HLSLDisallowsVariadicTemplates()) {
Diag(Tok, diag::err_hlsl_variadic_templates);
SkipUntil(tok::r_paren, StopBeforeMatch);
Actions.CorrectDelayedTyposInExpr(Expr);
Expand Down
2 changes: 1 addition & 1 deletion tools/clang/lib/Parse/ParseInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ ExprResult Parser::ParseBraceInitializer() {

if (Tok.is(tok::ellipsis)) {
// HLSL Change Starts
if (getLangOpts().HLSL) {
if (getLangOpts().HLSLDisallowsVariadicTemplates()) {
Diag(Tok, diag::err_hlsl_unsupported_construct) << "expansion";
InitExprsOk = false;
SkipUntil(tok::r_brace, StopBeforeMatch);
Expand Down
16 changes: 8 additions & 8 deletions tools/clang/lib/Parse/ParseTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,15 +516,15 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
SourceLocation EllipsisLoc;
if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {
// HLSL Change Starts
if (getLangOpts().HLSL) {
if (getLangOpts().HLSLDisallowsVariadicTemplates()) {
Diag(EllipsisLoc, diag::err_hlsl_variadic_templates);
return nullptr;
}
// HLSL Change Ends
Diag(EllipsisLoc,
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
: diag::ext_variadic_templates);
if (!getLangOpts().HLSL) // HLSL Change: HLSL has no C++98-compat warnings
Diag(EllipsisLoc, getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
: diag::ext_variadic_templates);
}

// Grab the template parameter name (if given)
Expand Down Expand Up @@ -620,9 +620,9 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
SourceLocation EllipsisLoc;
if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {
// HLSL Change Starts
if (getLangOpts().HLSL)
if (getLangOpts().HLSLDisallowsVariadicTemplates())
Comment thread
llvm-beanz marked this conversation as resolved.
Diag(EllipsisLoc, diag::err_hlsl_variadic_templates);
else
else if (!getLangOpts().HLSL) // HLSL has no C++98-compat warnings
// HLSL Change Ends
Diag(EllipsisLoc, getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
Expand Down Expand Up @@ -1296,7 +1296,7 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
SourceLocation EllipsisLoc;
if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
{ // HLSL Change Starts
if (getLangOpts().HLSL) {
if (getLangOpts().HLSLDisallowsVariadicTemplates()) {
Diag(EllipsisLoc, diag::err_hlsl_unsupported_construct) << "ellipsis";
SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);
return true;
Expand Down
2 changes: 1 addition & 1 deletion tools/clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6079,7 +6079,7 @@ class HLSLExternalSource : public ExternalSemaSource {
if (isMatrix || isVector) {
Expr *expr = arg.getAsExpr();
llvm::APSInt constantResult;
if (expr != nullptr &&
if (expr != nullptr && !expr->isValueDependent() &&
expr->isIntegerConstantExpr(constantResult, *m_context)) {
if (CheckRangedTemplateArgument(argSrcLoc, constantResult,
isVector))
Expand Down
34 changes: 23 additions & 11 deletions tools/clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2555,19 +2555,23 @@ Sema::SubstituteExplicitTemplateArguments(

// Isolate our substituted parameters from our caller.
LocalInstantiationScope InstScope(*this, /*MergeWithOuterScope*/true);
// HLSL Change Begin - HLSL needs the parameter decls to instantiate parameter
// modifiers correctly.
SmallVector<ParmVarDecl *, 4> ParamDecls;

// Instantiate the types of each of the function parameters given the
// explicitly-specified template arguments. If the function has a trailing
// return type, substitute it after the arguments to ensure we substitute
// in lexical order.
if (Proto->hasTrailingReturn()) {
if (SubstParmTypes(Function->getLocation(),
Function->param_begin(), Function->getNumParams(),
if (SubstParmTypes(Function->getLocation(), Function->param_begin(),
Function->getNumParams(),
MultiLevelTemplateArgumentList(*ExplicitArgumentList),
ParamTypes))
ParamTypes, &ParamDecls))
return TDK_SubstitutionFailure;
}

// HLSL Change End

// Instantiate the return type.
QualType ResultType;
{
Expand All @@ -2594,22 +2598,30 @@ Sema::SubstituteExplicitTemplateArguments(
if (ResultType.isNull() || Trap.hasErrorOccurred())
return TDK_SubstitutionFailure;
}

// Instantiate the types of each of the function parameters given the
// explicitly-specified template arguments if we didn't do so earlier.
// HLSL Change Begin - Pass ParamDecls to SubstParmTypes to correctly
// instantiate parameter modifiers.
if (!Proto->hasTrailingReturn() &&
SubstParmTypes(Function->getLocation(),
Function->param_begin(), Function->getNumParams(),
SubstParmTypes(Function->getLocation(), Function->param_begin(),
Function->getNumParams(),
MultiLevelTemplateArgumentList(*ExplicitArgumentList),
ParamTypes))
ParamTypes, &ParamDecls))
return TDK_SubstitutionFailure;
// HLSL Change - End

if (FunctionType) {
// HLSL Change - FIX - We should move param mods to parameter QualTypes
// HLSL Change Begin - Pass ParamDecls to SubstParmTypes to correctly
// instantiate parameter modifiers.
SmallVector<hlsl::ParameterModifier, 4> ParamMods;
ParamMods.reserve(ParamDecls.size());
for (ParmVarDecl *Param : ParamDecls)
ParamMods.push_back(Param ? Param->getParamModifiers()
: hlsl::ParameterModifier());
Comment thread
llvm-beanz marked this conversation as resolved.
*FunctionType = BuildFunctionType(
ResultType, ParamTypes, Function->getLocation(),
Function->getDeclName(), Proto->getExtProtoInfo(),
cast<FunctionProtoType>(Function->getType())->getParamMods());
Function->getDeclName(), Proto->getExtProtoInfo(), ParamMods);
// HLSL Change - End
if (FunctionType->isNull() || Trap.hasErrorOccurred())
return TDK_SubstitutionFailure;
Expand Down
2 changes: 1 addition & 1 deletion tools/clang/lib/Sema/SemaTemplateVariadic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ bool Sema::CheckParameterPacksForExpansion(
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
bool HaveFirstPack = false;

if (getLangOpts().HLSL) {
if (getLangOpts().HLSLDisallowsVariadicTemplates()) {
Diag(EllipsisLoc, diag::err_hlsl_variadic_templates);
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions tools/clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4280,14 +4280,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// parameter packs in the type of the non-type template parameter, then
// it expands those parameter packs.
// HLSL Change Starts
if (LangOpts.HLSL) {
if (LangOpts.HLSLDisallowsVariadicTemplates()) {
S.Diag(D.getEllipsisLoc(), diag::err_hlsl_variadic_templates);
break;
}
// HLSL Change Ends
if (T->containsUnexpandedParameterPack())
T = Context.getPackExpansionType(T, None);
else
else if (!LangOpts.HLSL) // HLSL Change: HLSL has no C++98-compat warnings
S.Diag(D.getEllipsisLoc(),
LangOpts.CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
Expand Down
Loading
Loading