Browse Source

Test that demonstrate the "new 0" and show some other erroneus behaviour too.

Implemented CastExpression. ImplicitCast and ExplicitCast statement classes.

Fixed implicit constructor string generation.

Implemented CtorExpr.

All test cases pass.

Fixed indentations, streamlined the code.

Fixed regressions.

Fixed regressions.

Adding a test case not covered before.

Fixed, refactored and simplified things.

Still more fixes (0 to null ptr conversion, enum check). The additional test passes now too.
pull/395/head
Pyry Kontio 11 years ago committed by Joao Matos
parent
commit
99f643d13f
  1. 23
      src/AST/Expression.cs
  2. 4
      src/AST/Statement.cs
  3. 39
      src/Core/Parser/ASTConverter.cs
  4. 3
      src/CppParser/AST.cpp
  5. 7
      src/CppParser/AST.h
  6. 10
      src/CppParser/Bindings/CLI/AST.cpp
  7. 9
      src/CppParser/Bindings/CLI/AST.h
  8. 26
      src/CppParser/Bindings/CSharp/i686-pc-win32-msvc/AST.cs
  9. 28
      src/CppParser/Parser.cpp
  10. 7
      src/Generator/Generators/CSharp/CSharpExpressionPrinter.cs
  11. 114
      src/Generator/Passes/HandleDefaultParamValuesPass.cs
  12. 45
      tests/CSharpTemp/CSharpTemp.cpp
  13. 31
      tests/CSharpTemp/CSharpTemp.h

23
src/AST/Expression.cs

@ -36,12 +36,31 @@ namespace CppSharp.AST @@ -36,12 +36,31 @@ namespace CppSharp.AST
public override T Visit<T>(IExpressionVisitor<T> visitor)
{
return visitor.VisitBuiltinExpression(this);
return visitor.VisitExpression(this);
}
}
public class CastExpr : Expression
{
public Expression SubExpression;
public override T Visit<T>(IExpressionVisitor<T> visitor)
{
return visitor.VisitExpression(this);
}
}
public class CtorExpr : Expression
{
public Expression SubExpression;
public override T Visit<T>(IExpressionVisitor<T> visitor)
{
return visitor.VisitExpression(this);
}
}
public interface IExpressionVisitor<out T>
{
T VisitBuiltinExpression(BuiltinTypeExpression builtinType);
T VisitExpression(Expression exp);
}
}

4
src/AST/Statement.cs

@ -6,7 +6,9 @@ @@ -6,7 +6,9 @@
BinaryOperator,
DeclarationReference,
ConstructorReference,
CXXOperatorCall
CXXOperatorCall,
ImplicitCast,
ExplicitCast,
}
public abstract class Statement

39
src/Core/Parser/ASTConverter.cs

@ -847,24 +847,51 @@ namespace CppSharp @@ -847,24 +847,51 @@ namespace CppSharp
if (statement == null)
return null;
var expression = new AST.BuiltinTypeExpression();
expression.Declaration = this.typeConverter.declConverter.Visit(statement.Decl);
expression.String = statement.String;
AST.Expression expression;
switch (statement.Class)
{
case StatementClass.BinaryOperator:
expression = new AST.BuiltinTypeExpression();
expression.Class = AST.StatementClass.BinaryOperator;
break;
case StatementClass.DeclRefExprClass:
expression = new AST.BuiltinTypeExpression();
expression.Class = AST.StatementClass.DeclarationReference;
break;
case StatementClass.CXXConstructExprClass:
expression.Class = AST.StatementClass.ConstructorReference;
break;
case StatementClass.CXXOperatorCallExpr:
expression = new AST.BuiltinTypeExpression();
expression.Class = AST.StatementClass.CXXOperatorCall;
break;
case StatementClass.CXXConstructExprClass:
{
var ctorExp = new AST.CtorExpr();
ctorExp.SubExpression = VisitStatement(((Expression)statement).Subexpression);
expression = ctorExp;
expression.Class = AST.StatementClass.ConstructorReference;
break;
}
case StatementClass.ImplicitCastExpr:
{
var castExp = new AST.CastExpr();
castExp.SubExpression = VisitStatement(((Expression)statement).Subexpression);
expression = castExp;
expression.Class = AST.StatementClass.ImplicitCast;
break;
}
case StatementClass.ExplicitCastExpr:
{
var castExp = new AST.CastExpr();
castExp.SubExpression = VisitStatement(((Expression)statement).Subexpression);
expression = castExp;
expression.Class = AST.StatementClass.ExplicitCast;
break;
}
default:
expression = new AST.BuiltinTypeExpression();
break;
}
expression.Declaration = this.typeConverter.declConverter.Visit(statement.Decl);
expression.String = statement.String;
return expression;
}

3
src/CppParser/AST.cpp

@ -433,7 +433,8 @@ DEF_STRING(Statement, String) @@ -433,7 +433,8 @@ DEF_STRING(Statement, String)
Statement::Statement(const std::string& str, StatementClass stmtClass, Declaration* decl) : String(str), Class(stmtClass), Decl(decl) {}
Expression::Expression(const std::string& str, StatementClass stmtClass, Declaration* decl) : Statement(str, stmtClass, decl) {}
Expression::Expression(const std::string& str, StatementClass stmtClass, Declaration* decl, Expression* subexpr)
:Statement(str, stmtClass, decl), Subexpression(subexpr) {}
Parameter::Parameter() : Declaration(DeclarationKind::Parameter),
IsIndirect(false), HasDefaultValue(false), DefaultArgument(0) {}

7
src/CppParser/AST.h

@ -465,7 +465,9 @@ enum class StatementClass @@ -465,7 +465,9 @@ enum class StatementClass
BinaryOperator,
DeclRefExprClass,
CXXConstructExprClass,
CXXOperatorCallExpr
CXXOperatorCallExpr,
ImplicitCastExpr,
ExplicitCastExpr,
};
class CS_API Statement
@ -480,7 +482,8 @@ public: @@ -480,7 +482,8 @@ public:
class CS_API Expression : public Statement
{
public:
Expression(const std::string& str, StatementClass Class = StatementClass::Any, Declaration* decl = 0);
Expression(const std::string& str, StatementClass Class = StatementClass::Any, Declaration* decl = 0, Expression* subexpr = 0);
Expression* Subexpression;
};
class CS_API Parameter : public Declaration

10
src/CppParser/Bindings/CLI/AST.cpp

@ -1562,6 +1562,16 @@ CppSharp::Parser::AST::Expression^ CppSharp::Parser::AST::Expression::__CreateIn @@ -1562,6 +1562,16 @@ CppSharp::Parser::AST::Expression^ CppSharp::Parser::AST::Expression::__CreateIn
return gcnew CppSharp::Parser::AST::Expression((::CppSharp::CppParser::AST::Expression*) native.ToPointer());
}
CppSharp::Parser::AST::Expression^ CppSharp::Parser::AST::Expression::Subexpression::get()
{
return (((::CppSharp::CppParser::AST::Expression*)NativePtr)->Subexpression == nullptr) ? nullptr : gcnew CppSharp::Parser::AST::Expression((::CppSharp::CppParser::AST::Expression*)((::CppSharp::CppParser::AST::Expression*)NativePtr)->Subexpression);
}
void CppSharp::Parser::AST::Expression::Subexpression::set(CppSharp::Parser::AST::Expression^ value)
{
((::CppSharp::CppParser::AST::Expression*)NativePtr)->Subexpression = (::CppSharp::CppParser::AST::Expression*)value->NativePtr;
}
CppSharp::Parser::AST::Parameter::Parameter(::CppSharp::CppParser::AST::Parameter* native)
: CppSharp::Parser::AST::Declaration((::CppSharp::CppParser::AST::Declaration*)native)
{

9
src/CppParser/Bindings/CLI/AST.h

@ -214,7 +214,9 @@ namespace CppSharp @@ -214,7 +214,9 @@ namespace CppSharp
BinaryOperator = 1,
DeclRefExprClass = 2,
CXXConstructExprClass = 3,
CXXOperatorCallExpr = 4
CXXOperatorCallExpr = 4,
ImplicitCastExpr = 5,
ExplicitCastExpr = 6
};
public enum struct TemplateSpecializationKind
@ -1211,6 +1213,11 @@ namespace CppSharp @@ -1211,6 +1213,11 @@ namespace CppSharp
Expression(::CppSharp::CppParser::AST::Expression* native);
static Expression^ __CreateInstance(::System::IntPtr native);
property CppSharp::Parser::AST::Expression^ Subexpression
{
CppSharp::Parser::AST::Expression^ get();
void set(CppSharp::Parser::AST::Expression^);
}
};
public ref class Parameter : CppSharp::Parser::AST::Declaration

26
src/CppParser/Bindings/CSharp/i686-pc-win32-msvc/AST.cs

@ -137,7 +137,9 @@ namespace CppSharp @@ -137,7 +137,9 @@ namespace CppSharp
BinaryOperator = 1,
DeclRefExprClass = 2,
CXXConstructExprClass = 3,
CXXOperatorCallExpr = 4
CXXOperatorCallExpr = 4,
ImplicitCastExpr = 5,
ExplicitCastExpr = 6
}
public enum TemplateSpecializationKind
@ -4170,7 +4172,7 @@ namespace CppSharp @@ -4170,7 +4172,7 @@ namespace CppSharp
public unsafe partial class Expression : CppSharp.Parser.AST.Statement, IDisposable
{
[StructLayout(LayoutKind.Explicit, Size = 32)]
[StructLayout(LayoutKind.Explicit, Size = 36)]
public new partial struct Internal
{
[FieldOffset(0)]
@ -4179,6 +4181,9 @@ namespace CppSharp @@ -4179,6 +4181,9 @@ namespace CppSharp
[FieldOffset(4)]
public global::System.IntPtr Decl;
[FieldOffset(32)]
public global::System.IntPtr Subexpression;
[SuppressUnmanagedCodeSecurity]
[DllImport("CppSharp.CppParser.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="??0Expression@AST@CppParser@CppSharp@@QAE@ABV0123@@Z")]
@ -4204,7 +4209,7 @@ namespace CppSharp @@ -4204,7 +4209,7 @@ namespace CppSharp
private static Expression.Internal* __CopyValue(Expression.Internal native)
{
var ret = Marshal.AllocHGlobal(32);
var ret = Marshal.AllocHGlobal(36);
CppSharp.Parser.AST.Expression.Internal.cctor_1(ret, new global::System.IntPtr(&native));
return (Expression.Internal*) ret;
}
@ -4228,6 +4233,21 @@ namespace CppSharp @@ -4228,6 +4233,21 @@ namespace CppSharp
}
base.Dispose(disposing);
}
public CppSharp.Parser.AST.Expression Subexpression
{
get
{
var __ptr = (Internal*)__Instance.ToPointer();
return (__ptr->Subexpression == IntPtr.Zero) ? null : CppSharp.Parser.AST.Expression.__CreateInstance(__ptr->Subexpression);
}
set
{
var __ptr = (Internal*)__Instance.ToPointer();
__ptr->Subexpression = value == (CppSharp.Parser.AST.Expression) null ? global::System.IntPtr.Zero : value.__Instance;
}
}
}
public unsafe partial class Parameter : CppSharp.Parser.AST.Declaration, IDisposable

28
src/CppParser/Parser.cpp

@ -2510,8 +2510,13 @@ AST::Expression* Parser::WalkExpression(clang::Expr* Expr) @@ -2510,8 +2510,13 @@ AST::Expression* Parser::WalkExpression(clang::Expr* Expr)
case Stmt::CXXFunctionalCastExprClass:
case Stmt::CXXReinterpretCastExprClass:
case Stmt::CXXStaticCastExprClass:
return new AST::Expression(GetStringFromStatement(Expr), StatementClass::ExplicitCastExpr,
0,
WalkExpression(cast<CastExpr>(Expr)->getSubExpr()));
case Stmt::ImplicitCastExprClass:
return WalkExpression(cast<CastExpr>(Expr)->getSubExprAsWritten());
return new AST::Expression(GetStringFromStatement(Expr), StatementClass::ImplicitCastExpr,
0,
WalkExpression(cast<CastExpr>(Expr)->getSubExpr()));
case Stmt::CXXOperatorCallExprClass:
return new AST::Expression(GetStringFromStatement(Expr), StatementClass::CXXOperatorCallExpr,
WalkDeclaration(cast<CXXOperatorCallExpr>(Expr)->getCalleeDecl()));
@ -2521,17 +2526,22 @@ AST::Expression* Parser::WalkExpression(clang::Expr* Expr) @@ -2521,17 +2526,22 @@ AST::Expression* Parser::WalkExpression(clang::Expr* Expr)
auto ConstructorExpr = cast<CXXConstructExpr>(Expr);
if (ConstructorExpr->getNumArgs() == 1)
{
auto Arg = ConstructorExpr->getArg(0);
auto TemporaryExpr = dyn_cast<MaterializeTemporaryExpr>(Arg);
if (TemporaryExpr)
if (ConstructorExpr->isElidable())
{
auto Cast = dyn_cast<CastExpr>(TemporaryExpr->GetTemporaryExpr());
if (Cast && Cast->getSubExprAsWritten()->getStmtClass() != Stmt::IntegerLiteralClass)
return WalkExpression(Cast->getSubExprAsWritten());
return WalkExpression(ConstructorExpr->getArg(0));
}
else
{
return new AST::Expression(GetStringFromStatement(Expr), StatementClass::CXXConstructExprClass,
WalkDeclaration(ConstructorExpr->getConstructor()),
WalkExpression(ConstructorExpr->getArg(0)));
}
}
else
{
return new AST::Expression(GetStringFromStatement(Expr), StatementClass::CXXConstructExprClass,
WalkDeclaration(ConstructorExpr->getConstructor()));
}
return new AST::Expression(GetStringFromStatement(Expr), StatementClass::CXXConstructExprClass,
WalkDeclaration(ConstructorExpr->getConstructor()));
}
case Stmt::MaterializeTemporaryExprClass:
return WalkExpression(cast<MaterializeTemporaryExpr>(Expr)->GetTemporaryExpr());

7
src/Generator/Generators/CSharp/CSharpExpressionPrinter.cs

@ -15,8 +15,7 @@ namespace CppSharp.Generators.CSharp @@ -15,8 +15,7 @@ namespace CppSharp.Generators.CSharp
public static class CSharpExpressionPrinterExtensions
{
public static CSharpExpressionPrinterResult CSharpValue(this Expression value,
CSharpExpressionPrinter printer)
public static CSharpExpressionPrinterResult CSharpValue(this Expression value, CSharpExpressionPrinter printer)
{
return value.Visit(printer);
}
@ -25,11 +24,11 @@ namespace CppSharp.Generators.CSharp @@ -25,11 +24,11 @@ namespace CppSharp.Generators.CSharp
public class CSharpExpressionPrinter : IExpressionPrinter<CSharpExpressionPrinterResult>,
IExpressionVisitor<CSharpExpressionPrinterResult>
{
public CSharpExpressionPrinterResult VisitBuiltinExpression(BuiltinTypeExpression builtinType)
public CSharpExpressionPrinterResult VisitExpression(Expression expr)
{
return new CSharpExpressionPrinterResult()
{
Value = builtinType.ToString(),
Value = expr.ToString(),
};
}

114
src/Generator/Passes/HandleDefaultParamValuesPass.cs

@ -28,7 +28,7 @@ namespace CppSharp.Passes @@ -28,7 +28,7 @@ namespace CppSharp.Passes
if (CheckForDefaultPointer(desugared, parameter))
continue;
bool? defaultConstruct = CheckForDefaultConstruct(desugared, parameter);
bool? defaultConstruct = CheckForDefaultConstruct(desugared, parameter.DefaultArgument);
if (defaultConstruct == null ||
(!Driver.Options.MarshalCharAsManagedChar &&
parameter.Type.Desugar().IsPrimitiveType(PrimitiveType.UChar)))
@ -39,10 +39,13 @@ namespace CppSharp.Passes @@ -39,10 +39,13 @@ namespace CppSharp.Passes
if (defaultConstruct == true)
continue;
if (CheckForEnumValue(parameter, desugared))
if (CheckForEnumValue(parameter.DefaultArgument, desugared))
continue;
CheckForAnonExpression(desugared, parameter);
CheckForDefaultEmptyChar(parameter, desugared);
}
GenerateOverloads(function, overloadIndices);
@ -50,6 +53,21 @@ namespace CppSharp.Passes @@ -50,6 +53,21 @@ namespace CppSharp.Passes
return result;
}
private bool CheckForAnonExpression(Type desugared, Parameter parameter)
{
var cast = parameter.DefaultArgument as CastExpr;
if (cast != null)
{
if (cast.SubExpression is BuiltinTypeExpression)
{
// The output string is correct in the deepest expression. Copy it to the outernmost.
cast.String = cast.SubExpression.String;
return true;
}
}
return true;
}
private static bool CheckForDefaultPointer(Type desugared, Parameter parameter)
{
if (desugared.IsPointer())
@ -62,20 +80,42 @@ namespace CppSharp.Passes @@ -62,20 +80,42 @@ namespace CppSharp.Passes
return false;
}
private bool? CheckForDefaultConstruct(Type desugared, Parameter parameter)
private bool? CheckForDefaultConstruct(Type desugared, Expression arg)
{
Method ctor = parameter.DefaultArgument.Declaration as Method;
// Unwrapping the constructor and a possible cast
Method ctor = null;
CastExpr castExpression = null;
CtorExpr ctorExpression = null;
if (arg is CtorExpr)
{
ctorExpression = (CtorExpr)arg;
ctor = (Method)ctorExpression.Declaration;
}
else if (arg is CastExpr && ((CastExpr)arg).SubExpression is CtorExpr)
{
castExpression = (CastExpr)arg;
ctorExpression = (CtorExpr)castExpression.SubExpression;
ctor = (Method)ctorExpression.Declaration;
}
else
{
return false;
}
var innerArg = ctorExpression.SubExpression;
if (ctor == null || !ctor.IsConstructor)
return false;
// Unwrapping the underlying type behind a possible pointer/reference
Type type;
desugared.IsPointerTo(out type);
type = type ?? desugared;
Class decl;
if (!type.TryGetClass(out decl))
return false;
TypeMap typeMap;
TypeMap typeMap;
if (Driver.TypeDatabase.FindTypeMap(decl, type, out typeMap))
{
Type typeInSignature;
@ -102,43 +142,79 @@ namespace CppSharp.Passes @@ -102,43 +142,79 @@ namespace CppSharp.Passes
Enumeration @enum;
if (typeInSignature.TryGetEnum(out @enum))
{
return true;
var argCast = (CastExpr)arg;
Expression literal = ((CtorExpr)argCast.SubExpression).SubExpression;
if (CheckForEnumValue(literal, desugared))
{
argCast.String = literal.String;
argCast.SubExpression.String = literal.String;
return true;
}
else
{
return false;
}
}
if (mappedTo == "string" && ctor.Parameters.Count == 0)
{
parameter.DefaultArgument.String = "\"\"";
arg.String = "\"\"";
return true;
}
}
parameter.DefaultArgument.String = string.Format("new {0}", parameter.DefaultArgument.String);
if (ctor.Parameters.Count > 0 && ctor.Parameters[0].OriginalName == "_0")
parameter.DefaultArgument.String = parameter.DefaultArgument.String.Replace("(0)", "()");
if (innerArg is CtorExpr || innerArg is CastExpr)
{
Type innerDesugared = ctor.Parameters[0].Type.Desugar();
CheckForDefaultConstruct(innerDesugared, innerArg);
if (innerDesugared.IsPointer() && innerArg.String == "0")
innerArg.String = "";
arg.String = string.Format("new {0}({1})", ctor.Name, innerArg.String);
}
else if (innerArg != null)
{
Type innerDesugared = ctor.Parameters[0].Type.Desugar();
CheckForEnumValue(innerArg, innerDesugared);
arg.String = string.Format("new {0}({1})", ctor.Name, innerArg.String);
}
else
{
arg.String = string.Format("new {0}()", ctor.Name);
}
return decl.IsValueType ? true : (bool?) null;
}
private static bool CheckForEnumValue(Parameter parameter, Type desugared)
private static bool CheckForEnumValue(Expression arg, Type desugared)
{
var enumItem = parameter.DefaultArgument.Declaration as Enumeration.Item;
// Handle a simple cast (between int and enum, for example)
var argCast = arg as CastExpr;
Expression literal;
if (argCast != null)
literal = argCast.SubExpression;
else
literal = arg;
// The default case
var enumItem = literal.Declaration as Enumeration.Item;
if (enumItem != null)
{
parameter.DefaultArgument.String = string.Format("{0}{1}{2}.{3}",
arg.String = string.Format("{0}{1}{2}.{3}",
desugared.IsPrimitiveType() ? "(int) " : string.Empty,
string.IsNullOrEmpty(enumItem.Namespace.Namespace.Name)
? string.Empty
: enumItem.Namespace.Namespace.Name + ".", enumItem.Namespace.Name, enumItem.Name);
return true;
}
var call = parameter.DefaultArgument.Declaration as Function;
if (call != null || parameter.DefaultArgument.Class == StatementClass.BinaryOperator)
// Handle cases like "Flags::Flag1 | Flags::Flag2"
var call = arg.Declaration as Function;
if ((call != null && call.ReturnType.Type.IsEnum()) || arg.Class == StatementClass.BinaryOperator)
{
string @params = regexFunctionParams.Match(parameter.DefaultArgument.String).Groups[1].Value;
string @params = regexFunctionParams.Match(arg.String).Groups[1].Value;
if (@params.Contains("::"))
parameter.DefaultArgument.String = regexDoubleColon.Replace(@params, desugared + ".");
arg.String = regexDoubleColon.Replace(@params, desugared + ".");
else
parameter.DefaultArgument.String = regexName.Replace(@params, desugared + ".$1");
arg.String = regexName.Replace(@params, desugared + ".$1");
return true;
}
return false;

45
tests/CSharpTemp/CSharpTemp.cpp

@ -31,6 +31,39 @@ const Foo& Bar::operator[](int i) const @@ -31,6 +31,39 @@ const Foo& Bar::operator[](int i) const
return m_foo;
}
Quux::Quux()
{
}
Quux::Quux(int i)
{
}
Quux::Quux(char c)
{
}
Quux::Quux(Foo f)
{
}
QColor::QColor()
{
}
QColor::QColor(Qt::GlobalColor color)
{
}
Qux::Qux()
{
@ -294,10 +327,22 @@ void MethodsWithDefaultValues::defaultMappedToZeroEnum(QFlags<Flags> qFlags) @@ -294,10 +327,22 @@ void MethodsWithDefaultValues::defaultMappedToZeroEnum(QFlags<Flags> qFlags)
{
}
void MethodsWithDefaultValues::defaultImplicitCtorInt(Quux arg)
{
}
void MethodsWithDefaultValues::defaultImplicitCtorChar(Quux arg)
{
}
void MethodsWithDefaultValues::defaultIntWithLongExpression(unsigned int i)
{
}
void MethodsWithDefaultValues::defaultRefTypeEnumImplicitCtor(const QColor &fillColor)
{
}
void HasPrivateOverrideBase::privateOverride(int i)
{
}

31
tests/CSharpTemp/CSharpTemp.h

@ -16,6 +16,18 @@ protected: @@ -16,6 +16,18 @@ protected:
int P;
};
class DLL_API Quux
{
public:
Quux();
Quux(int i);
Quux(char c);
Quux(Foo f);
private:
int priv;
};
class DLL_API Qux
{
public:
@ -216,6 +228,21 @@ private: @@ -216,6 +228,21 @@ private:
#define DEFAULT_INT (2 * 1000UL + 500UL)
namespace Qt
{
enum GlobalColor {
black,
white,
};
}
class QColor
{
public:
QColor();
QColor(Qt::GlobalColor color);
};
class DLL_API MethodsWithDefaultValues
{
public:
@ -236,7 +263,11 @@ public: @@ -236,7 +263,11 @@ public:
void defaultNonEmptyCtor(QGenericArgument arg = QGenericArgument(0));
void defaultMappedToEnum(QFlags<Flags> qFlags = Flags::Flag1);
void defaultMappedToZeroEnum(QFlags<Flags> qFlags = 0);
void defaultImplicitCtorInt(Quux arg = 0);
void defaultImplicitCtorChar(Quux arg = 'a');
void defaultImplicitCtorFoo(Quux arg = Foo());
void defaultIntWithLongExpression(unsigned int i = DEFAULT_INT);
void defaultRefTypeEnumImplicitCtor(const QColor &fillColor = Qt::white);
};
class DLL_API HasPrivateOverrideBase

Loading…
Cancel
Save