提交 85aa8d3b 编写于 作者: A AlekseyTs

C#: Request use-site diagnostics while checking if type caught or thrown...

C#: Request use-site diagnostics while checking if type caught or thrown derives from System.Exception and report it (the use-site diagnostics) if the check failed. Fixes #132. (changeset 1351406)
上级 f960f3a0
......@@ -300,11 +300,13 @@ private BoundThrowStatement BindThrow(ThrowStatementSyntax node, DiagnosticBag d
// If the expression is a lambda, anonymous method, or method group then it will
// have no compile-time type; give the same error as if the type was wrong.
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
if ((object)type == null || !type.IsErrorType() && !Compilation.IsExceptionType(type.EffectiveTypeNoUseSiteDiagnostics))
if ((object)type == null || !type.IsErrorType() && !Compilation.IsExceptionType(type.EffectiveType(ref useSiteDiagnostics), ref useSiteDiagnostics))
{
diagnostics.Add(ErrorCode.ERR_BadExceptionType, exprSyntax.Location);
hasErrors = true;
diagnostics.Add(exprSyntax, useSiteDiagnostics);
}
}
}
......@@ -3011,7 +3013,6 @@ private BoundCatchBlock BindCatchBlock(CatchClauseSyntax node, ArrayBuilder<Boun
{
bool hasError = false;
TypeSymbol type = null;
TypeSymbol effectiveType = null;
BoundExpression boundFilter = null;
var declaration = node.Declaration;
if (declaration != null)
......@@ -3029,12 +3030,14 @@ private BoundCatchBlock BindCatchBlock(CatchClauseSyntax node, ArrayBuilder<Boun
}
else
{
effectiveType = type.EffectiveTypeNoUseSiteDiagnostics;
if (!Compilation.IsExceptionType(effectiveType))
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
TypeSymbol effectiveType = type.EffectiveType(ref useSiteDiagnostics);
if (!Compilation.IsExceptionType(effectiveType, ref useSiteDiagnostics))
{
// "The type caught or thrown must be derived from System.Exception"
Error(diagnostics, ErrorCode.ERR_BadExceptionType, declaration.Type);
hasError = true;
diagnostics.Add(declaration.Type, useSiteDiagnostics);
}
}
}
......
......@@ -129,9 +129,8 @@ internal override bool IsAttributeType(ITypeSymbol type)
return IsAttributeType((TypeSymbol)type);
}
internal bool IsExceptionType(TypeSymbol type)
internal bool IsExceptionType(TypeSymbol type, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
return IsEqualOrDerivedFromWellKnownClass(type, WellKnownType.System_Exception, ref useSiteDiagnostics);
}
......
......@@ -235,6 +235,11 @@ internal TypeSymbol EffectiveTypeNoUseSiteDiagnostics
}
}
internal TypeSymbol EffectiveType(ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
return this.IsTypeParameter() ? ((TypeParameterSymbol)this).EffectiveBaseClass(ref useSiteDiagnostics) : this;
}
/// <summary>
/// Returns true if this type derives from a given type.
/// </summary>
......
......@@ -2154,6 +2154,65 @@ static void Main()
Diagnostic(ErrorCode.ERR_BindToBogusProp1, "new Indexers()[null]").WithArguments("Indexers.this[?]", "Indexers.get_Item(?)"));
}
[WorkItem(939928, "DevDiv")]
[WorkItem(132, "CodePlex")]
[Fact]
public void MissingBaseTypeForCatch()
{
var source1 = @"
using System;
public class GeneralException : Exception {}";
CSharpCompilation comp1 = CreateCompilationWithMscorlib(source1, assemblyName: "Base");
var source2 = @"
public class SpecificException : GeneralException
{}";
CSharpCompilation comp2 = CreateCompilationWithMscorlib(source2, new MetadataReference[] { new CSharpCompilationReference(comp1)});
var source3 = @"
class Test
{
static void Main(string[] args)
{
try
{
SpecificException e = null;
throw e;
}
catch (SpecificException)
{
}
}
}";
CSharpCompilation comp3 = CreateCompilationWithMscorlib(source3, new MetadataReference[] { new CSharpCompilationReference(comp2) });
DiagnosticDescription[] expected =
{
// (9,23): error CS0155: The type caught or thrown must be derived from System.Exception
// throw e;
Diagnostic(ErrorCode.ERR_BadExceptionType, "e").WithLocation(9, 23),
// (9,23): error CS0012: The type 'GeneralException' is defined in an assembly that is not referenced. You must add a reference to assembly 'Base, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// throw e;
Diagnostic(ErrorCode.ERR_NoTypeDef, "e").WithArguments("GeneralException", "Base, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(9, 23),
// (11,20): error CS0155: The type caught or thrown must be derived from System.Exception
// catch (SpecificException)
Diagnostic(ErrorCode.ERR_BadExceptionType, "SpecificException").WithLocation(11, 20),
// (11,20): error CS0012: The type 'GeneralException' is defined in an assembly that is not referenced. You must add a reference to assembly 'Base, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// catch (SpecificException)
Diagnostic(ErrorCode.ERR_NoTypeDef, "SpecificException").WithArguments("GeneralException", "Base, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(11, 20)
};
comp3.VerifyDiagnostics(expected);
comp3 = CreateCompilationWithMscorlib(source3, new MetadataReference[] { comp2.EmitToImageReference() });
comp3.VerifyDiagnostics(expected);
}
/// <summary>
/// Trivial definitions of special types that will be required for testing use site errors in
/// the attributes emitted for unsafe assemblies.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册