summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/core/slang-string-util.cpp25
-rw-r--r--source/core/slang-string-util.h3
-rw-r--r--source/slang/slang-check-expr.cpp24
-rw-r--r--source/slang/slang-ir-check-differentiability.cpp5
-rw-r--r--source/slang/slang-ir-util.h12
-rw-r--r--source/slang/slang-ir.cpp12
-rw-r--r--source/slang/slang-language-server-completion.cpp2
-rw-r--r--source/slang/slang-language-server.cpp22
-rw-r--r--source/slang/slang-language-server.h1
-rw-r--r--tests/diagnostics/property-readonly-lvalue.slang14
10 files changed, 105 insertions, 15 deletions
diff --git a/source/core/slang-string-util.cpp b/source/core/slang-string-util.cpp
index fb062de76..a6a18d4a0 100644
--- a/source/core/slang-string-util.cpp
+++ b/source/core/slang-string-util.cpp
@@ -392,6 +392,31 @@ ComPtr<ISlangBlob> StringUtil::createStringBlob(const String& string)
return (fromChar == toChar || string.indexOf(fromChar) == Index(-1)) ? string : calcCharReplaced(string.getUnownedSlice(), fromChar, toChar);
}
+String StringUtil::replaceAll(UnownedStringSlice text, UnownedStringSlice subStr, UnownedStringSlice replacement)
+{
+ StringBuilder builder;
+ for (Index i = 0; i < text.getLength();)
+ {
+ if (i + subStr.getLength() >= text.getLength())
+ {
+ builder.append(text.subString(i, text.getLength() - i));
+ break;
+ }
+ if (text.subString(i, subStr.getLength()) == subStr)
+ {
+ builder.append(replacement);
+ i += subStr.getLength();
+ }
+ else
+ {
+ builder.append(text[i]);
+ i++;
+ }
+ }
+ return builder.produceString();
+}
+
+
/* static */void StringUtil::appendStandardLines(const UnownedStringSlice& text, StringBuilder& out)
{
const char* cur = text.begin();
diff --git a/source/core/slang-string-util.h b/source/core/slang-string-util.h
index 4b9a4d5d1..7e5733cbb 100644
--- a/source/core/slang-string-util.h
+++ b/source/core/slang-string-util.h
@@ -87,6 +87,9 @@ struct StringUtil
static String calcCharReplaced(const UnownedStringSlice& slice, char fromChar, char toChar);
static String calcCharReplaced(const String& string, char fromChar, char toChar);
+ /// Replaces all occurrances of subStr with replacement.
+ static String replaceAll(UnownedStringSlice text, UnownedStringSlice subStr, UnownedStringSlice replacement);
+
/// Create a blob from a string
static ComPtr<ISlangBlob> createStringBlob(const String& string);
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index 05a6ed249..22bc2cae8 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -372,7 +372,24 @@ namespace Slang
{
expr->type.isLeftValue = false;
}
-
+ else
+ {
+ // If we are accessing a readonly property, then the result
+ // is not an l-value.
+ if (auto propertyDecl = as<PropertyDecl>(declRef.getDecl()))
+ {
+ bool isLValue = false;
+ for (auto member : propertyDecl->members)
+ {
+ if (as<SetterDecl>(member) || as< RefAccessorDecl>(member))
+ {
+ isLValue = true;
+ break;
+ }
+ }
+ expr->type.isLeftValue = isLValue;
+ }
+ }
return expr;
}
}
@@ -3322,7 +3339,10 @@ namespace Slang
// A swizzle can be used as an l-value as long as there
// were no duplicates in the list of components
- swizExpr->type.isLeftValue = !anyDuplicates;
+ swizExpr->type.isLeftValue = !anyDuplicates &&
+ swizExpr->base &&
+ swizExpr->base->type &&
+ swizExpr->base->type.isLeftValue;
return swizExpr;
}
diff --git a/source/slang/slang-ir-check-differentiability.cpp b/source/slang/slang-ir-check-differentiability.cpp
index b937fe052..ddb70d779 100644
--- a/source/slang/slang-ir-check-differentiability.cpp
+++ b/source/slang/slang-ir-check-differentiability.cpp
@@ -85,7 +85,12 @@ public:
switch (func->getOp())
{
case kIROp_ForwardDifferentiate:
+ if (auto fwdDerivative = func->getOperand(0)->findDecoration<IRForwardDerivativeDecoration>())
+ return isDifferentiableFunc(fwdDerivative->getForwardDerivativeFunc(), level);
+ return isDifferentiableFunc(func->getOperand(0), level);
case kIROp_BackwardDifferentiate:
+ if (auto bwdDerivative = func->getOperand(0)->findDecoration<IRUserDefinedBackwardDerivativeDecoration>())
+ return isDifferentiableFunc(bwdDerivative->getBackwardDerivativeFunc(), level);
return isDifferentiableFunc(func->getOperand(0), level);
default:
break;
diff --git a/source/slang/slang-ir-util.h b/source/slang/slang-ir-util.h
index ff6298f39..0b377a3d1 100644
--- a/source/slang/slang-ir-util.h
+++ b/source/slang/slang-ir-util.h
@@ -152,9 +152,15 @@ inline bool isGenericParam(IRInst* param)
inline IRInst* unwrapAttributedType(IRInst* type)
{
- while (auto attrType = as<IRAttributedType>(type))
- type = attrType->getBaseType();
- return type;
+ for (;;)
+ {
+ if (auto attrType = as<IRAttributedType>(type))
+ type = attrType->getBaseType();
+ else if (auto rateType = as<IRRateQualifiedType>(type))
+ type = rateType->getValueType();
+ else
+ return type;
+ }
}
// Remove hlsl's 'unorm' and 'snorm' modifiers
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index 6a3a26bd5..cf58e6cd4 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -4848,19 +4848,20 @@ namespace Slang
{
IRType* type = nullptr;
auto basePtrType = as<IRPtrTypeBase>(basePtr->getDataType());
- if (auto arrayType = as<IRArrayType>(basePtrType->getValueType()))
+ auto valueType = unwrapAttributedType(basePtrType->getValueType());
+ if (auto arrayType = as<IRArrayType>(valueType))
{
type = arrayType->getElementType();
}
- else if (auto vectorType = as<IRVectorType>(basePtrType->getValueType()))
+ else if (auto vectorType = as<IRVectorType>(valueType))
{
type = vectorType->getElementType();
}
- else if (auto matrixType = as<IRMatrixType>(basePtrType->getValueType()))
+ else if (auto matrixType = as<IRMatrixType>(valueType))
{
type = getVectorType(matrixType->getElementType(), matrixType->getColumnCount());
}
- else if (const auto basicType = as<IRBasicType>(basePtrType->getValueType()))
+ else if (const auto basicType = as<IRBasicType>(valueType))
{
// HLSL support things like float.x, in which case we just return the base pointer.
return basePtr;
@@ -4884,10 +4885,11 @@ namespace Slang
for (auto access : accessChain)
{
auto basePtrType = cast<IRPtrTypeBase>(basePtr->getDataType());
+ auto valueType = unwrapAttributedType(basePtrType->getValueType());
IRType* resultType = nullptr;
if (auto structKey = as<IRStructKey>(access))
{
- auto structType = as<IRStructType>(basePtrType->getValueType());
+ auto structType = as<IRStructType>(valueType);
SLANG_RELEASE_ASSERT(structType);
for (auto field : structType->getFields())
{
diff --git a/source/slang/slang-language-server-completion.cpp b/source/slang/slang-language-server-completion.cpp
index ae1a0e9c2..58ee766cc 100644
--- a/source/slang/slang-language-server-completion.cpp
+++ b/source/slang/slang-language-server-completion.cpp
@@ -35,7 +35,7 @@ static const char* kStmtKeywords[] = {
"__generic", "__exported", "import", "enum", "break", "continue",
"discard", "defer", "cbuffer", "tbuffer", "func", "is",
"as", "nullptr", "none", "true", "false", "functype",
- "sizeof", "alignof"};
+ "sizeof", "alignof", "__target_switch", "__intrinsic_asm"};
static const char* hlslSemanticNames[] = {
"register",
diff --git a/source/slang/slang-language-server.cpp b/source/slang/slang-language-server.cpp
index 3a21fa278..cea5d0151 100644
--- a/source/slang/slang-language-server.cpp
+++ b/source/slang/slang-language-server.cpp
@@ -1469,9 +1469,10 @@ SlangResult LanguageServer::formatting(const LanguageServerProtocol::DocumentFor
}
if (m_formatOptions.clangFormatLocation.getLength() == 0)
m_formatOptions.clangFormatLocation = findClangFormatTool();
- m_formatOptions.fileName = canonicalPath;
+ auto options = getFormatOptions(m_workspace, m_formatOptions);
+ options.fileName = canonicalPath;
List<TextRange> exclusionRange = extractFormattingExclusionRanges(doc->getText().getUnownedSlice());
- auto edits = formatSource(doc->getText().getUnownedSlice(), -1, -1, -1, exclusionRange, m_formatOptions);
+ auto edits = formatSource(doc->getText().getUnownedSlice(), -1, -1, -1, exclusionRange, options);
auto textEdits = translateTextEdits(doc, edits);
m_connection->sendResult(&textEdits, responseId);
return SLANG_OK;
@@ -1491,7 +1492,7 @@ SlangResult LanguageServer::rangeFormatting(const LanguageServerProtocol::Docume
Index endOffset = doc->getOffset(endLine, endCol);
if (m_formatOptions.clangFormatLocation.getLength() == 0)
m_formatOptions.clangFormatLocation = findClangFormatTool();
- auto options = m_formatOptions;
+ auto options = getFormatOptions(m_workspace, m_formatOptions);
if (!m_formatOptions.allowLineBreakInRangeFormatting)
options.behavior = FormatBehavior::PreserveLineBreak;
List<TextRange> exclusionRange = extractFormattingExclusionRanges(doc->getText().getUnownedSlice());
@@ -1520,7 +1521,7 @@ SlangResult LanguageServer::onTypeFormatting(const LanguageServerProtocol::Docum
Index line, col;
doc->zeroBasedUTF16LocToOneBasedUTF8Loc(args.position.line, args.position.character, line, col);
auto cursorOffset = doc->getOffset(line, col);
- auto options = m_formatOptions;
+ auto options = getFormatOptions(m_workspace, m_formatOptions);
if (!m_formatOptions.allowLineBreakInOnTypeFormatting)
options.behavior = FormatBehavior::PreserveLineBreak;
List<TextRange> exclusionRange = extractFormattingExclusionRanges(doc->getText().getUnownedSlice());
@@ -1760,6 +1761,19 @@ void LanguageServer::logMessage(int type, String message)
m_connection->sendCall(LanguageServerProtocol::LogMessageParams::methodName, &args);
}
+FormatOptions LanguageServer::getFormatOptions(Workspace* workspace, FormatOptions inOptions)
+{
+ FormatOptions result = inOptions;
+ if (workspace->rootDirectories.getCount())
+ {
+ result.clangFormatLocation = StringUtil::replaceAll(
+ result.clangFormatLocation.getUnownedSlice(),
+ toSlice("${workspaceFolder}"),
+ workspace->rootDirectories.getFirst().getUnownedSlice());
+ }
+ return result;
+}
+
SlangResult LanguageServer::tryGetMacroHoverInfo(
WorkspaceVersion* version, DocumentVersion* doc, Index line, Index col, JSONValue responseId)
{
diff --git a/source/slang/slang-language-server.h b/source/slang/slang-language-server.h
index 175ccf0f1..b17991714 100644
--- a/source/slang/slang-language-server.h
+++ b/source/slang/slang-language-server.h
@@ -152,6 +152,7 @@ private:
void registerCapability(const char* methodName);
void logMessage(int type, String message);
+ FormatOptions getFormatOptions(Workspace* workspace, FormatOptions inOptions);
SlangResult tryGetMacroHoverInfo(
WorkspaceVersion* version,
DocumentVersion* doc,
diff --git a/tests/diagnostics/property-readonly-lvalue.slang b/tests/diagnostics/property-readonly-lvalue.slang
new file mode 100644
index 000000000..ec7263f17
--- /dev/null
+++ b/tests/diagnostics/property-readonly-lvalue.slang
@@ -0,0 +1,14 @@
+//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK):
+// use read-only property as l-value
+
+struct MyType
+{
+ property float3 prop { get { return float3(1, 2, 3);}}
+}
+
+void test()
+{
+ MyType t;
+ // CHECK: {{.*}}error 30047: argument passed to parameter '0' must be l-value.
+ t.prop.x += 1.0;
+}