diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2017-11-03 12:25:46 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-11-03 12:25:46 -0700 |
| commit | cc98fd4606222ec1d18878d5e8278dc32910076b (patch) | |
| tree | 2a7f8ca6cef978aecfe814ea2b34bafb89c390bf /source/slang | |
| parent | 8fe947b2fbbdaa747fb7acc7624d9290bba52086 (diff) | |
Fix #248 (#249)
* Fix up test runner output for compute.
We want compute-based tests to produce a `.actual` file when compilation fails, so we can easily diagnose the issue. I thought I'd added this capability previous, but it seemst to not be present any more.
* Compute result types for constructor decls
Fixes #246
When the parser sees an `init()` declaration, it can't easily know what type is is supposed to return, so it leaves the type as NULL. This was causing some downstream crashes.
Rather than special-case every site that cares about the result type of a callable, we will instead ensure that we install an actual result type on an initializer/constructor as part of its semantic checking.
This code needs to handle both the case where the initializer is declared inside a type, as well as the case where it is declared inside an `extension`.
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/check.cpp | 46 | ||||
| -rw-r--r-- | source/slang/diagnostic-defs.h | 1 | ||||
| -rw-r--r-- | source/slang/mangle.cpp | 7 |
3 files changed, 53 insertions, 1 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 0c35c4bf4..3116bbbd2 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -3228,6 +3228,46 @@ namespace Slang decl->SetCheckState(DeclCheckState::Checked); } + // Figure out what type an initializer/constructor declaration + // is supposed to return. In most cases this is just the type + // declaration that its declaration is nested inside. + RefPtr<Type> findResultTypeForConstructorDecl(ConstructorDecl* decl) + { + // We want to look at the parent of the declaration, + // but if the declaration is generic, the parent will be + // the `GenericDecl` and we need to skip past that to + // the grandparent. + // + auto parent = decl->ParentDecl; + auto genericParent = dynamic_cast<GenericDecl*>(parent); + if (genericParent) + { + parent = genericParent->ParentDecl; + } + + // Now look at the type of the parent (or grandparent). + if (auto aggTypeDecl = dynamic_cast<AggTypeDecl*>(parent)) + { + // We are nested in an aggregate type declaration, + // so the result type of the initializer will just + // be the surrounding type. + return DeclRefType::Create( + getSession(), + makeDeclRef(aggTypeDecl)); + } + else if (auto extDecl = dynamic_cast<ExtensionDecl*>(parent)) + { + // We are nested inside an extension, so the result + // type needs to be the type being extended. + return extDecl->targetType.type; + } + else + { + getSink()->diagnose(decl, Diagnostics::initializerNotInsideType); + return nullptr; + } + } + void visitConstructorDecl(ConstructorDecl* decl) { if (decl->IsChecked(DeclCheckState::Checked)) return; @@ -3237,6 +3277,12 @@ namespace Slang { paramDecl->type = CheckUsableType(paramDecl->type); } + + // We need to compute the result tyep for this declaration, + // since it wasn't filled in for us. + decl->ReturnType.type = findResultTypeForConstructorDecl(decl); + + decl->SetCheckState(DeclCheckState::CheckedHeader); // TODO(tfoley): check body diff --git a/source/slang/diagnostic-defs.h b/source/slang/diagnostic-defs.h index cca1c4869..cc7db7eb4 100644 --- a/source/slang/diagnostic-defs.h +++ b/source/slang/diagnostic-defs.h @@ -318,6 +318,7 @@ DIAGNOSTIC(38003, Error, entryPointSymbolNotAFunction, "entry point '$0' must be DIAGNOSTIC(38100, Error, typeDoesntImplementInterfaceRequirement, "type '$0' does not provide required interface member '$1'") DIAGNOSTIC(38101, Error, thisExpressionOutsideOfTypeDecl, "'this' expression can only be used in members of an aggregate type") +DIAGNOSTIC(38102, Error, initializerNotInsideType, "an 'init' declaration is only allowed inside a type or 'extension' declaration") // // 4xxxx - IL code generation. diff --git a/source/slang/mangle.cpp b/source/slang/mangle.cpp index 63e54d065..2cdd6a9e1 100644 --- a/source/slang/mangle.cpp +++ b/source/slang/mangle.cpp @@ -275,7 +275,12 @@ namespace Slang emitType(context, GetType(paramDeclRef)); } - emitType(context, GetResultType(callableDeclRef)); + // Don't print result type for an initializer/constructor, + // since it is implicit in the qualified name. + if (!callableDeclRef.As<ConstructorDecl>()) + { + emitType(context, GetResultType(callableDeclRef)); + } } } |
