diff --git a/clang/docs/BiShengCLanguageUserManual.md b/clang/docs/BiShengCLanguageUserManual.md index 373069651ffea9e4c16892a2368691482debaa55..72d3f5b51b45f824ee9e78400b2cd156c4433058 100644 --- a/clang/docs/BiShengCLanguageUserManual.md +++ b/clang/docs/BiShengCLanguageUserManual.md @@ -209,17 +209,21 @@ void foo1() { // do nothing }; -void int::foo2(int* this) { // 实例成员函数,第一个入参是 this +void int::foo2(int* this) { // 实例成员函数,第一个入参是 This 指针,指向当前int类型的实例 // do something } -void int::foo2() { // 静态成员函数 +void int::foo3(int this) { // 实例成员函数,第一个入参是 This 实例,不是 This 指针 + // do something +} + +void int::foo4() { // 静态成员函数 // do something } ``` -其中,type-name 可以是基础类型如 `int`, `float` 等,也可以是用户自定义的结构体等,符合 C 语言对类型的定义规则。下面是更多的用法示例: +其中,type-name 可以是基础类型如 `int`, `float` 等,也可以是用户自定义的结构体等,符合 C 语言对类型的定义规则,此外可以使用`This` 来简化表示当前类型。下面是更多的用法示例: ```c // case 1 @@ -233,24 +237,30 @@ void int::print(int* this){ // 定义 struct S1{}; // 错误使用 S,在 C 语言里 struct S 才是一个类型 void S1::print(struct S1* this); // error: must use 'struct' tag to refer to type 'S' +void struct S1::print(struct S1* this); // Ok,修正后的声明 // case 3 typedef struct { }S2; void S2::print(S2* this); // Ok, S2 是 typedef 后的 struct S2 + +// case 4 +void S2::print(This this); // Ok, This 表示当前类型 struct S2 +void S2::print(This* this); // Ok, This* 表示指向当前类型 struct S2 的指针 + ``` 采用这样的语法设计有一个好处,那就是我们很方便就可以给已有类型增加成员函数而不用侵入式修改源码。 ### 关于 `this` -在上面的成员函数的例子中,参数列表中的第一个参数如果为 `this`(如果有 `this`,它也只能是第一个参数),它表示指向该成员函数对应类型实例的指针,它是一个“实例成员函数”。如果成员函数参数列表中,没有 `this` 存在,则表示这是一个“静态成员函数”。 +在上面的成员函数的例子中,参数列表中的第一个参数如果为 `this`(如果有 `this`,它也只能是第一个参数),它表示该成员函数对应类型实例(This this)、或指向该实例的指针(This* this),它是一个“实例成员函数”。如果成员函数参数列表中,没有 `this` 存在,则表示这是一个“静态成员函数”。 ```c typedef struct {/*...*/} M; void M::f(M* this, int i) {} // 实例成员函数 typedef struct {/*...*/} N; -void N::f() {} // 静态成原函数 +void N::f() {} // 静态成员函数 int main() { M x; @@ -677,7 +687,7 @@ typedef MyS_T_int = struct V; int main() { Int64 a = 5; //等价于int a = 5; - MyS s; //等价于struct S s = 5; + MyS s; //等价于struct S s; int b = 2; MyPointerType c = &b; //等价于int* c = &b; Array_3 d = {1,2,3}; //等价于int d[3] = {1,2,3}; @@ -2841,7 +2851,7 @@ void test(int a, int *owned b, int *c, struct S d) { int *borrow p8 = &const g; //p8的被借用对象是g // 被借用对象是函数入参 - int *borrow p9 = &mut a; //p9的被借用对象是g + int *borrow p9 = &mut a; //p9的被借用对象是a int *borrow p10 = &mut *b; //p10的被借用对象是b int *borrow p11 = &mut *c; //p11的被借用对象是c int *borrow p12 = &mut d.a; //p12的被借用对象是d.a @@ -2889,7 +2899,7 @@ void test() { 在2.1中我们提到过,对于借用,我们有这样的生命周期约束:**借用变量的生命周期,不能比被借用对象的生命周期长**。 举例来说: ```C -//本例中,p的生命周期为[3,4],被借用对象local的生命周期为[1,4],满足生命周期约束 +//本例中,p的生命周期为[2,4],被借用对象local的生命周期为[1,4],满足生命周期约束 void test1() { int local = 5; //#1 int *borrow p = &mut local; //#2 @@ -2937,7 +2947,7 @@ void test4() { use(p); //#10 } -//本例中,p的生命周期为[3,4],被借用对象x的生命周期为[1,3],不满足生命周期约束,error +//本例中,p的生命周期为[2,4],被借用对象x的生命周期为[1,3],不满足生命周期约束,error void test5() { int *owned x = safe_malloc(5); //#1 int *borrow p = &mut *x; //#2 diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 4112a2589fc252228e16f27aae4cc9d8ae63a326..cdaca83b0f61cfce23f20183ff8f4f356ea5ed1f 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1030,6 +1030,7 @@ public: return withFastQualifiers(Qualifiers::Borrow); } bool isConstBorrow() const; + bool isConstPointee() const; QualType addConstBorrow(const ASTContext &Context); QualType removeConstForBorrow(const ASTContext &Context); bool hasBorrow() const; diff --git a/clang/include/clang/Basic/BSC/DiagnosticBSCSemaKinds.td b/clang/include/clang/Basic/BSC/DiagnosticBSCSemaKinds.td index 7eff2d0fa29da3abcd669a7ae89a823c59fdae05..e027a4609fc7bc3f7608dc11501d8cc1cb28f68b 100644 --- a/clang/include/clang/Basic/BSC/DiagnosticBSCSemaKinds.td +++ b/clang/include/clang/Basic/BSC/DiagnosticBSCSemaKinds.td @@ -2,8 +2,18 @@ def note_no_this_parameter : Note<"found the following member function %0 which doesn't have a 'this' parameter">; def err_no_instance_member : Error< "no instance member named %0 in %1; did you mean to use '::' instead of '%select{.|->}2'?">; +def err_cvrqualified_member_type_unsupported : Error< + "type of member function is wrong, CVR qualified type is unsupported, but found '%0'">; +def err_cvrqualified_this_type_unsupported : Error< + "owned type requires a pointer, '%0' is invalid">; def err_this_type_unsupported : Error< - "type of parameter 'this' is wrong, expected 'This*' or '%0*', but found '%1'">; + "type of parameter 'this' is wrong, expected 'This*' or 'This' or '%0*' or '%0', but found '%1'">; +def err_incompatible_pointer_cast : Error< + "incompatible conversion from pointer type '%0' to non-pointer type '%1' in member function call">; +def err_incompatible_const_cast : Error< + "incompatible conversion from const type '%0' to non-const type '%1' in member function call">; +def err_incompatible_owned_cast : Error< + "incompatible conversion from non owned type '%0' to owned type '%1' in member function call">; // BSC attributes warnings and errors. def warn_attribute_no_pointers : Warning< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index efa6a48afe4ad187adf1ff7852cbba63b201da86..c11f8fee69c60e794d9b4eab2bd396c3be7b46ee 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -12428,6 +12428,9 @@ public: bool CheckOperatorDeclNeedAddToContext(Declarator &D); bool CheckOperatorFunReturnTypeIsLegal(FunctionDecl *FnDecl); bool FindSafeFeatures(const FunctionDecl* FnDecl); + void CheckMemberThisCallAccess(Expr *ActualArgExpr, QualType formalType); + bool CheckNeedCastQualifiedType(QualType actualType, QualType formalType); + bool CheckNeedReborrowPointerType(QualType actualType, QualType formalType); #endif bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType); diff --git a/clang/lib/AST/BSC/TypeBSC.cpp b/clang/lib/AST/BSC/TypeBSC.cpp index 500319785035978ce304d1481cd8da3a76f9decb..bba9b782c748f8eec03dac9fdf0fce091154196a 100644 --- a/clang/lib/AST/BSC/TypeBSC.cpp +++ b/clang/lib/AST/BSC/TypeBSC.cpp @@ -304,6 +304,16 @@ bool QualType::isConstBorrow() const { return false; } +bool QualType::isConstPointee() const { + QualType QT = QualType(getTypePtr(), getLocalFastQualifiers()); + while (QT->isPointerType()) { + QT = QT->getPointeeType(); + } + if (QT.isLocalConstQualified()) + return true; + return false; +} + QualType QualType::addConstBorrow(const ASTContext &Context) { SmallVector Qualifiers; int PointerNum = 0; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e12d507db652fd806512da8a6ce7864f3107bd7c..8985133fdb8a8da0a259e48eaaf5b87d5a8edd00 100755 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -14673,6 +14673,22 @@ void Sema::CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D) { } } +static bool CheckThisParamQualifiers(QualType thisParamT) { + if (!thisParamT->isPointerType()) { + // not allow This owned/borrow + // borrow not pointer is alredy checked in the Sema::BuildQualifiedType + if (thisParamT.isOwnedQualified()) { + bool IsOwnedStruct = thisParamT->isOwnedStructureType() || + thisParamT->isOwnedTemplateSpecializationType(); + // only owned struct ok + if (!(IsOwnedStruct && thisParamT.getQualifiers().hasOnlyOwned())) { + return false; + } + } + } + return true; +} + /// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() /// to introduce parameters into function prototype scope. Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D @@ -14731,17 +14747,33 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D } bool IsThisParam = false; const Type* TypePtr = ExtendedType.getTypePtrOrNull(); + if (TypePtr) TypePtr = TypePtr->getCanonicalTypeUnqualified().getTypePtrOrNull(); // if TypePtr is nullptr, it is not a BSCMethod if (TypePtr && DeclarationName(II).getAsString() == "this" && !isDestructor) { if (ParamSize == 0) { + // check memberfunction type whether has cvr-qualifiers + // cvr-qualified type is not allowed to define member functions + Qualifiers ETQ = ExtendedType.getQualifiers(); + if (ETQ.hasCVRQualifiers() && + !((TypePtr->isOwnedStructureType() || TypePtr->isOwnedTemplateSpecializationType()) && + ETQ.hasOnlyOwned())) { + Diag(D.getBeginLoc(), diag::err_cvrqualified_member_type_unsupported) + << ExtendedType.getAsString(); + D.setInvalidType(true); + } + if (!CheckThisParamQualifiers(parmDeclType)) { + Diag(D.getBeginLoc(), diag::err_cvrqualified_this_type_unsupported) + << parmDeclType.getAsString(); + D.setInvalidType(true); + } auto ThisTypePtr = parmDeclType.getTypePtrOrNull(); if (ThisTypePtr) { - ThisTypePtr = ThisTypePtr->getPointeeType().getTypePtrOrNull(); - if (ThisTypePtr) - ThisTypePtr = - ThisTypePtr->getCanonicalTypeUnqualified().getTypePtrOrNull(); + if (ThisTypePtr->isPointerType()) { + ThisTypePtr = ThisTypePtr->getPointeeType().getTypePtrOrNull(); + } + ThisTypePtr = ThisTypePtr->getCanonicalTypeUnqualified().getTypePtrOrNull(); } if (DS.getTypeSpecType() != clang::TST_This && TypePtr != ThisTypePtr) { Diag(D.getBeginLoc(), diag::err_this_type_unsupported) @@ -14779,28 +14811,30 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D } } - #if ENABLE_BSC +#if ENABLE_BSC if (getLangOpts().BSC) if (TraitDecl *TD = TryDesugarTrait(parmDeclType)) parmDeclType = DesugarTraitToStructTrait(TD, parmDeclType, D.getBeginLoc()); - #endif +#endif // Temporarily put parameter variables in the translation unit, not // the enclosing context. This prevents them from accidentally // looking like class members in C++. - #if ENABLE_BSC +#if ENABLE_BSC // Use This* as BSCMethod parameter, // For example void struct S::f(This* this); if (getLangOpts().BSC && TypePtr && DS.getTypeSpecType() == clang::TST_This) { Qualifiers ThisQual = parmDeclType->getPointeeType().getLocalQualifiers(); Qualifiers ThisPointerQual = parmDeclType.getLocalQualifiers(); - parmDeclType = Context.getQualifiedType(ExtendedType, ThisQual); - // for Destructor, skip set pointer; + QualType desugarThisType = Context.getQualifiedType(ExtendedType, ThisQual); + // for Destructor or not pointer This parm, skip set pointer; // For example ~S(This this); - if (!isDestructor) { + if (!isDestructor && parmDeclType->isPointerType()) { parmDeclType = Context.getQualifiedType( - Context.getPointerType(parmDeclType), ThisPointerQual); + Context.getPointerType(desugarThisType), ThisPointerQual); + } else { + parmDeclType = Context.getQualifiedType(desugarThisType, ThisPointerQual); // FIXME: check This Qualifiers } TInfo = Context.CreateTypeSourceInfo(parmDeclType); // if EntendedType is a generic type, @@ -14830,7 +14864,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D } } } - #endif +#endif ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(), D.getBeginLoc(), D.getIdentifierLoc(), II, parmDeclType, TInfo, SC); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 02e767acbb4edf92ee3dc182ed4ba8bd57acbfdb..cd1482829f89736de925065c1cb977c453f42054 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6370,6 +6370,71 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, return false; } +#if ENABLE_BSC +void Sema::CheckMemberThisCallAccess(Expr *ActualArgExpr, QualType formalType) { + SourceLocation SL = ActualArgExpr->getBeginLoc(); + QualType actualType = ActualArgExpr->getType(); // the type of actual param, as type of foo + if (actualType->isPointerType() && !formalType->isPointerType()) { + Diag(SL, diag::err_incompatible_pointer_cast) << actualType.getAsString() << formalType.getAsString(); + return; + } + if ((!actualType.isOwnedQualified() && formalType.isOwnedQualified()) || + (!actualType->isPointerType() && formalType->isPointerType() && formalType.isOwnedQualified())) { + Diag(SL, diag::err_incompatible_owned_cast) << actualType.getAsString() << formalType.getAsString(); + return; + } + // pointer qualifiers have already been implicitly cast to non-qualified type, for example: + // ImplicitCastExpr 0xXX 'int *' + // | `-DeclRefExpr 0xXX 'int *const volatile' lvalue Var 0xXX 'p' + if (!actualType->isPointerType() && !formalType->isPointerType()) { + if (actualType.isConstQualified() && !formalType.isConstQualified()) { + Diag(SL, diag::err_incompatible_const_cast) << actualType.getAsString() << formalType.getAsString(); + return; + } + } + if (!actualType->isPointerType() && formalType->isPointerType()) { + if (actualType.isConstQualified() && !formalType->getPointeeType().isConstQualified()) { + Diag(SL, diag::err_incompatible_const_cast) << actualType.getAsString() << formalType.getAsString(); + return; + } + } + if (actualType->isPointerType() && formalType->isPointerType()) { + if (actualType->getPointeeType().isConstQualified() && !formalType->getPointeeType().isConstQualified()) { + Diag(SL, diag::err_incompatible_const_cast) << actualType.getAsString() << formalType.getAsString(); + return; + } + } +} + +bool Sema::CheckNeedCastQualifiedType(QualType actualType, QualType formalType) { + if (actualType->isPointerType() && formalType->isPointerType()) { + if (actualType.getCVRQualifiers() != formalType.getCVRQualifiers()) { + return true; + } + actualType = actualType->getPointeeType(); + formalType = formalType->getPointeeType(); + } + if (actualType.getCVRQualifiers() != formalType.getCVRQualifiers()) { + return true; + } + return false; +} + +bool Sema::CheckNeedReborrowPointerType(QualType actualType, QualType formalType) { + if (!actualType->isPointerType() || !formalType->isPointerType()){ + return false; + } + if (actualType.isOwnedQualified() && !formalType.isOwnedQualified()) { + return true; + } + if (!(actualType.isOwnedQualified() || actualType.isBorrowQualified()) && + formalType.isBorrowQualified()) { + return true; + } + return false; +} +#endif + bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, const FunctionProtoType *Proto, unsigned FirstParam, ArrayRef Args, @@ -6384,7 +6449,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, bool Invalid = false; size_t ArgIx = 0; - #if ENABLE_BSC +#if ENABLE_BSC // If the BSCMethod contains `this` parameter, the function is an instance // member function, It does not need to explicitly pass parameters when // calling, So we need to build an ast for `this` parameter. @@ -6400,41 +6465,53 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, if (!Member) return true; - Expr *ImplicitArg = Member->getBase(); // parameter for foo->getA + Expr *ImplicitArg = Member->getBase(); // parameter for foo->getA, include actual param type if (!ImplicitArg) return true; const FunctionProtoType *FPT = dyn_cast(Member->getType()); - QualType thisQPT = FPT->getParamType(0); + QualType thisQPT = FPT->getParamType(0); // the type of formal parameter, as type of this + CheckMemberThisCallAccess(ImplicitArg, thisQPT); + bool isNeedReborrow = CheckNeedReborrowPointerType(ImplicitArg->getType(), thisQPT); if (!Member->isArrow()) { // foo.getA - // When the first parameter `this` of member function is borrow qualified, - // add `&mut` or `&const` when desugaring. - UnaryOperator::Opcode UO = - thisQPT.isBorrowQualified() ? (thisQPT.isConstBorrow() ? UO_AddrConst : UO_AddrMut) : UO_AddrOf; + if (thisQPT->isPointerType()) { + // When the first parameter `this` of member function is pointer, + // add `&mut` or `&const` when desugaring. + UnaryOperator::Opcode UO = + thisQPT.isBorrowQualified() ? (thisQPT.isConstBorrow() ? UO_AddrConst : UO_AddrMut) : UO_AddrOf; + ImplicitArg = UnaryOperator::Create( + this->Context, ImplicitArg, UO, FPT->getParamType(0), VK_PRValue, + OK_Ordinary, SourceLocation(), false, + this->CurFPFeatureOverrides()); + } else { + ImplicitArg = ImplicitCastExpr::Create( + this->Context, ImplicitArg->getType(), CK_NoOp, ImplicitArg, + nullptr, VK_PRValue, this->CurFPFeatureOverrides()); + } + } + if (isNeedReborrow) { + UnaryOperator::Opcode UO = thisQPT->getPointeeType().isConstQualified() + ? UO_AddrConstDeref : UO_AddrMutDeref; ImplicitArg = UnaryOperator::Create( - this->Context, ImplicitArg, UO, - this->Context.getPointerType(ImplicitArg->getType()), VK_PRValue, - OK_Ordinary, SourceLocation(), false, - this->CurFPFeatureOverrides()); + this->Context, ImplicitArg, UO, FPT->getParamType(0), VK_PRValue, + OK_Ordinary, SourceLocation(), false, + this->CurFPFeatureOverrides()); } - - auto typeQual = thisQPT.getTypePtr()->getPointeeType().getCVRQualifiers(); - if (typeQual & Qualifiers::Const || typeQual & Qualifiers::Volatile || thisQPT.isBorrowQualified()) { - ImplicitCastExpr *Implict = ImplicitCastExpr::Create( + bool isNeedCast = CheckNeedCastQualifiedType(ImplicitArg->getType(), thisQPT); + if (isNeedCast) { + ImplicitArg = ImplicitCastExpr::Create( this->Context, FPT->getParamType(0), CK_NoOp, ImplicitArg, nullptr, VK_PRValue, FPOptionsOverride()); - AllArgs.push_back(Implict); - } else { - AllArgs.push_back(ImplicitArg); - } + } + AllArgs.push_back(ImplicitArg); // Set desugar flag true after push_back the arg. Callee->IsDesugaredBSCMethodCall = true; FirstParam = FirstParam + 1; } } - #endif - +#endif + // Continue to check argument types (even if we have too few/many args). for (unsigned i = FirstParam; i < NumParams; i++) { QualType ProtoArgType = Proto->getParamType(i); @@ -6443,7 +6520,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, ParmVarDecl *Param = FDecl ? FDecl->getParamDecl(i) : nullptr; if (ArgIx < Args.size()) { Arg = Args[ArgIx++]; - #if ENABLE_BSC +#if ENABLE_BSC if (getLangOpts().BSC && TryDesugarTrait(ProtoArgType) && !TryDesugarTrait(Arg->IgnoreParenCasts()->getType())) { Expr *TraitDesugaredExpr = ConvertParmTraitToStructTrait( diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index ba5143084c51a22502eb77d8e32bb45e1b7aecca..a53524dd7b02c09a42119c17d723469db17cf984 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1029,18 +1029,6 @@ MemberExpr *Sema::BuildMemberExpr( const TemplateArgumentListInfo *TemplateArgs) { assert((!IsArrow || Base->isPRValue()) && "-> base must be a pointer prvalue"); - #if ENABLE_BSC - if (getLangOpts().BSC && IsArrow && Base->getType().isConstBorrow()) { - const auto *BMD = dyn_cast_or_null(Member); - const auto *FPT = dyn_cast_or_null(Ty); - if (BMD && FPT) { - if (BMD->getHasThisParam() && FPT->getNumParams() > 0 && - !FPT->getParamType(0).isConstBorrow()) - Diag(OpLoc, diag::err_borrow_qualcheck_incompatible) - << Base->getType() << FPT->getParamType(0); - } - } - #endif MemberExpr *E = MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc, Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty, diff --git a/clang/test/BSC/Negative/Generic/GenericTypeMethods/generic_type_method_ast/generic_type_method_ast.cbs b/clang/test/BSC/Negative/Generic/GenericTypeMethods/generic_type_method_ast/generic_type_method_ast.cbs index a3c5c88c033ae8c3382b3c7df1906ef4dfc01a30..b038678fb55a0deca4f231755953c1e650c8ec11 100644 --- a/clang/test/BSC/Negative/Generic/GenericTypeMethods/generic_type_method_ast/generic_type_method_ast.cbs +++ b/clang/test/BSC/Negative/Generic/GenericTypeMethods/generic_type_method_ast/generic_type_method_ast.cbs @@ -64,7 +64,7 @@ int main() { // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'struct MyStruct (*)(struct MyStruct *)' // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} 'struct MyStruct (struct MyStruct *)' lvalue .foo 0x{{[^ ]*}} // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'MyStruct':'struct MyStruct' lvalue Var 0x{{[^ ]*}} 's' 'MyStruct':'struct MyStruct' -// CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <, col:3> 'MyStruct *' prefix '&' cannot overflow +// CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <, col:3> 'struct MyStruct *' prefix '&' cannot overflow // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'MyStruct':'struct MyStruct' lvalue Var 0x{{[^ ]*}} 's' 'MyStruct':'struct MyStruct' // CHECK-NEXT: CallExpr 0x{{[^ ]*}} 'struct MyStruct':'struct MyStruct' // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'struct MyStruct (*)(struct MyStruct *)' diff --git a/clang/test/BSC/Negative/Method/BuiltInType/int_this_param_check/int_this_param_check.cbs b/clang/test/BSC/Negative/Method/BuiltInType/int_this_param_check/int_this_param_check.cbs index 665ae3bea4580b45f512b2dfd1db9897c48083b0..d791aef53d64403de100c1b73b3037769c9b4af9 100644 --- a/clang/test/BSC/Negative/Method/BuiltInType/int_this_param_check/int_this_param_check.cbs +++ b/clang/test/BSC/Negative/Method/BuiltInType/int_this_param_check/int_this_param_check.cbs @@ -1,4 +1,4 @@ // RUN: %clang_cc1 -verify %s -void int::increase(int this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'int*', but found 'int'}} -} \ No newline at end of file +void int::increase(float this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'This' or 'int*' or 'int', but found 'float'}} +} diff --git a/clang/test/BSC/Negative/Method/Enum/enum_member_func_ast/enum_member_func_ast.cbs b/clang/test/BSC/Negative/Method/Enum/enum_member_func_ast/enum_member_func_ast.cbs index 12a580313ee14a6bb3975c59ca12a5cc6ecea011..95185ae9eb75865a3cd3a30f3de15abb95f737f7 100644 --- a/clang/test/BSC/Negative/Method/Enum/enum_member_func_ast/enum_member_func_ast.cbs +++ b/clang/test/BSC/Negative/Method/Enum/enum_member_func_ast/enum_member_func_ast.cbs @@ -54,7 +54,7 @@ int main() { // CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'int (*)(enum E *)' // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} 'int (enum E *)' lvalue .getA 0x{{[^ ]*}} // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'F':'enum E' lvalue Var 0x{{[^ ]*}} 'foo' 'F':'enum E' -// CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <, col:3> 'F *' prefix '&' cannot overflow +// CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <, col:3> 'enum E *' prefix '&' cannot overflow // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'F':'enum E' lvalue Var 0x{{[^ ]*}} 'foo' 'F':'enum E' // CHECK-NEXT: DeclStmt 0x{{[^ ]*}} // CHECK-NEXT: VarDecl 0x{{[^ ]*}} col:7 x 'int' cinit diff --git a/clang/test/BSC/Negative/Method/Enum/enum_this_param_check/enum_this_param_check.cbs b/clang/test/BSC/Negative/Method/Enum/enum_this_param_check/enum_this_param_check.cbs index 308239afdc5ecf38298f7b3724e0ab3aac9022c6..f3147510dc65f45bb8fd0d490ccaa32597650ee6 100644 --- a/clang/test/BSC/Negative/Method/Enum/enum_this_param_check/enum_this_param_check.cbs +++ b/clang/test/BSC/Negative/Method/Enum/enum_this_param_check/enum_this_param_check.cbs @@ -5,5 +5,5 @@ enum E { X4 }; -int enum E::getA(enum E this); // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'enum E*', but found 'enum E'}} +int enum E::getA(int this); // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'This' or 'enum E*' or 'enum E', but found 'int'}} diff --git a/clang/test/BSC/Negative/Method/Struct/struct_this_param_check/struct_this_param_check.cbs b/clang/test/BSC/Negative/Method/Struct/struct_this_param_check/struct_this_param_check.cbs index de42ac7df746455830ab51b70a902243243b596e..511300103a0d111784f2c51a5a98b759b1f3dbda 100644 --- a/clang/test/BSC/Negative/Method/Struct/struct_this_param_check/struct_this_param_check.cbs +++ b/clang/test/BSC/Negative/Method/Struct/struct_this_param_check/struct_this_param_check.cbs @@ -2,6 +2,6 @@ struct Foo { }; -int struct Foo::getA(struct Foo this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'struct Foo*', but found 'struct Foo'}} - return 1; +int struct Foo::getA(int this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'This' or 'struct Foo*' or 'struct Foo', but found 'int'}} + return 0; } diff --git a/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_call/owned_struct_member_function_call/owned_struct_member_function_call.cbs b/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_call/owned_struct_member_function_call/owned_struct_member_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..a64d59e3ca5450b5f2c9ea6bbfdb46caf85f10dd --- /dev/null +++ b/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_call/owned_struct_member_function_call/owned_struct_member_function_call.cbs @@ -0,0 +1,109 @@ +// RUN: %clang_cc1 -verify %s + +owned struct Bar { +public: + int a; +}; + + +T* owned safe_malloc(T value); +void free_owned(T* owned p); + +int Bar::getA(This this) { + return this.a; // expected-error {{memory leak because temporary variable 'this' is owned or indirect owned type, please fix it}} +} + +int Bar::getA_2(const This this) { + return this.a; // expected-error {{memory leak because temporary variable 'this' is owned or indirect owned type, please fix it}} +} + +int Bar::getB(This* this) { + return this->a; +} + +int Bar::getB_2(const This* const this) { + return this->a; +} + +int Bar::getC(This* borrow this) { + return this->a; +} + +int Bar::getC_2(const This* borrow this) { + return this->a; +} + +void Bar::getD(This* owned this) { + free_owned(this); +} + +void test_This_actual_param() { + Bar bar = {.a = 1}; + const Bar bar2 = {.a = 2}; + int a = bar.getA(); // expect ok, run ok + int a2 = bar2.getA_2(); + int a3 = bar2.getA(); // expected-error {{incompatible conversion from const type 'const owned struct Bar' to non-const type 'owned struct Bar' in member function call}} + int a4 = bar2.getA_2(); + int b = bar.getB(); // expect ok, run ok + int b2 = bar.getB_2(); //expect ok, run ok + int b3 = bar2.getB(); // expected-error {{incompatible conversion from const type 'const owned struct Bar' to non-const type 'owned struct Bar *' in member function call}} + int b4 = bar2.getB_2(); + int c = bar.getC(); // expect ok, run ok + int c2 = bar.getC_2(); // expect ok, run ok + bar.getD(); // expected-error {{incompatible conversion from non owned type 'owned struct Bar' to owned type 'owned struct Bar *owned' in member function call}} +} + +void test_This_pointer_actual_param() { + Bar bar = {.a = 1}; + Bar * bar_p = &bar; + int a = bar_p->getA(); // expected-error {{incompatible conversion from pointer type 'owned struct Bar *' to non-pointer type 'owned struct Bar' in member function call}} + int b = bar_p->getB(); // expect ok, run ok + int b2 = bar_p->getB_2(); //expect ok, run ok + int c = bar_p->getC(); // expect ok, run ok + int c2 = bar_p->getC_2(); // expect ok, run ok + bar_p->getD(); // expected-error {{incompatible conversion from non owned type 'owned struct Bar *' to owned type 'owned struct Bar *owned' in member function call}} +} + +void test_const_This_pointer_actual_param() { + Bar bar = {.a = 1}; + const Bar * c_bar_p = &bar; + int a = c_bar_p->getA(); // expected-error {{incompatible conversion from pointer type 'const owned struct Bar *' to non-pointer type 'owned struct Bar' in member function call}} + int b = c_bar_p->getB(); // expected-error {{incompatible conversion from const type 'const owned struct Bar *' to non-const type 'owned struct Bar *' in member function call}} + int b2 = c_bar_p->getB_2(); //expect ok, run ok + int c = c_bar_p->getC(); // expected-error {{incompatible conversion from const type 'const owned struct Bar *' to non-const type 'owned struct Bar *borrow' in member function call}} + int c2 = c_bar_p->getC_2(); // expect ok, run ok + c_bar_p->getD(); // expected-error {{incompatible conversion from non owned type 'const owned struct Bar *' to owned type 'owned struct Bar *owned' in member function call}} +} + +void test_This_pointer_borrow_actual_param(void) { + Bar bar = {.a = 1}; + Bar *borrow bar_mut = &mut bar; + int a = bar_mut->getA(); // expected-error {{incompatible conversion from pointer type 'owned struct Bar *borrow' to non-pointer type 'owned struct Bar' in member function call}} + int b = bar_mut->getB(); // expect ok, run ok + int b2 = bar_mut->getB_2(); //expect ok, run ok + int c = bar_mut->getC(); // expect ok, run ok + int c2 = bar_mut->getC_2(); // expect ok, run ok + bar_mut->getD(); // expected-error {{incompatible conversion from non owned type 'owned struct Bar *borrow' to owned type 'owned struct Bar *owned' in member function call}} +} + +void test_const_This_pointer_borrow_actual_param(void) { + Bar bar = {.a = 1}; + const Bar *borrow c_bar_mut = &const bar; + int a = c_bar_mut->getA(); // expected-error {{incompatible conversion from pointer type 'const owned struct Bar *borrow' to non-pointer type 'owned struct Bar' in member function call}} + int b = c_bar_mut->getB(); // expected-error {{incompatible conversion from const type 'const owned struct Bar *borrow' to non-const type 'owned struct Bar *' in member function call}} + int b2 = c_bar_mut->getB_2(); //expect ok, run ok + int c = c_bar_mut->getC(); // expected-error {{incompatible conversion from const type 'const owned struct Bar *borrow' to non-const type 'owned struct Bar *borrow' in member function call}} + int c2 = c_bar_mut->getC_2(); // expect ok, run ok + c_bar_mut->getD(); // expected-error {{incompatible conversion from non owned type 'const owned struct Bar *borrow' to owned type 'owned struct Bar *owned' in member function call}} +} + +void test_This_pointer_owned_actual_param(void) { + Bar bar = {.a = 1}; + Bar * owned bar_owned = safe_malloc(bar); + int a = bar_owned->getA(); // expected-error {{incompatible conversion from pointer type 'owned struct Bar *owned' to non-pointer type 'owned struct Bar' in member function call}} + int b = bar_owned->getB(); // expect ok, run ok + int b2 = bar_owned->getB_2(); //expect ok, run ok + int c = bar_owned->getC(); // expect ok, run ok + int c2 = bar_owned->getC_2(); // expect ok, run ok + bar_owned->getD(); // expect ok, run ok +} diff --git a/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_call/owned_struct_member_function_call_safe/owned_struct_member_function_call_safe.cbs b/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_call/owned_struct_member_function_call_safe/owned_struct_member_function_call_safe.cbs new file mode 100644 index 0000000000000000000000000000000000000000..2c2b506cc0e15b3b20d28c141b63e32977cecbd8 --- /dev/null +++ b/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_call/owned_struct_member_function_call_safe/owned_struct_member_function_call_safe.cbs @@ -0,0 +1,124 @@ +// RUN: %clang_cc1 -verify %s +// #include + +owned struct Bar { +public: + int a; +}; +T* owned safe_malloc(T value); +void free_owned(T* owned p); + +// T* owned safe_malloc(T value) { +// T * p = (T *) malloc( sizeof(T) ); +// *p = value; +// return (T* owned)p; +// } + +// void free_owned(T* owned p) { +// free( (T*)p ); +// } + +safe int Bar::getA(This this) { + return this.a; // expected-error {{memory leak because temporary variable 'this' is owned or indirect owned type, please fix it}} +} + +safe int Bar::getB(This* this) { // expected-error {{unsafe parameter type is forbidden in the safe function}} + return this->a; // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} +} + +safe int Bar::getB_2(const This* this) { // expected-error {{unsafe parameter type is forbidden in the safe function}} + return this->a; // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} +} + +safe int Bar::getC(This* borrow this) { + this->a = 2; + return this->a; +} + +safe int Bar::getC_2(const This* borrow this) { + return this->a; +} + +safe void Bar::getD(This* owned this) { + free_owned(this); +} + +safe void test_This_actual_param(void) { + Bar bar = {.a = 1}; + int s_a = bar.getA(); // expect ok, run ok + int s_b = bar.getB(); // expect error, function getB is error + int s_b2 = bar.getB_2(); // expect error, function getB_2 is error + int s_c = bar.getC(); // expect ok, run ok + int s_c2 = bar.getC_2(); // expect ok, run ok + bar.getD(); // expected-error {{incompatible conversion from non owned type 'owned struct Bar' to owned type 'owned struct Bar *owned' in member function call}} +} + +void test_This_pointer_actual_param() { + Bar bar = {.a = 1}; + Bar * bar_p = &bar; + safe { + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_a = bar_p->getA(); // expected-error {{incompatible conversion from pointer type 'owned struct Bar *' to non-pointer type 'owned struct Bar' in member function call}} + int s_b = bar_p->getB(); // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_b2 = bar_p->getB_2(); // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_c = bar_p->getC(); // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_c2 = bar_p->getC_2(); // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + bar_p->getD(); // expected-error {{incompatible conversion from non owned type 'owned struct Bar *' to owned type 'owned struct Bar *owned' in member function call}} + } +} + +void test_const_This_pointer_actual_param() { + Bar bar = {.a = 1}; + const Bar * c_bar_p = &bar; + safe { + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_a = c_bar_p->getA(); // expected-error {{incompatible conversion from pointer type 'const owned struct Bar *' to non-pointer type 'owned struct Bar' in member function call}} + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_b = c_bar_p->getB(); // expected-error {{incompatible conversion from const type 'const owned struct Bar *' to non-const type 'owned struct Bar *' in member function call}} + int s_b2 = c_bar_p->getB_2(); // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_c = c_bar_p->getC(); // expected-error {{incompatible conversion from const type 'const owned struct Bar *' to non-const type 'owned struct Bar *borrow' in member function call}} + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_c2 = c_bar_p->getC_2(); // expect error, run error + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + c_bar_p->getD(); // expected-error {{incompatible conversion from non owned type 'const owned struct Bar *' to owned type 'owned struct Bar *owned' in member function call}} + } +} + +safe void test_This_pointer_borrow_actual_param(void) { + Bar bar = {.a = 1}; + Bar * borrow bar_mut = &mut bar; + int s_a = bar_mut->getA(); // expected-error {{incompatible conversion from pointer type 'owned struct Bar *borrow' to non-pointer type 'owned struct Bar' in member function call}} + int s_b = bar_mut->getB(); // expect error, function getB is error + int s_b2 = bar_mut->getB_2(); // expect error, function getB_2 is error + int s_c = bar_mut->getC(); // expect ok, run ok + int s_c2 = bar_mut->getC_2(); // expect ok, run ok + bar_mut->getD(); // expected-error {{incompatible conversion from non owned type 'owned struct Bar *borrow' to owned type 'owned struct Bar *owned' in member function call}} +} + +safe void test_const_This_pointer_borrow_actual_param(void) { + Bar bar = {.a = 1}; + const Bar *borrow c_bar_mut = &const bar; // incompatible borrow types, cannot cast 'const owned struct Bar *borrow' + int a = c_bar_mut->getA(); // expected-error {{incompatible conversion from pointer type 'const owned struct Bar *borrow' to non-pointer type 'owned struct Bar' in member function call}} + int b = c_bar_mut->getB(); // expected-error {{incompatible conversion from const type 'const owned struct Bar *borrow' to non-const type 'owned struct Bar *' in member function call}} + int b2 = c_bar_mut->getB_2(); // expect error, function getB_2 is error + int c = c_bar_mut->getC(); // expected-error {{incompatible conversion from const type 'const owned struct Bar *borrow' to non-const type 'owned struct Bar *borrow' in member function call}} + int c2 = c_bar_mut->getC_2(); // expect ok, run ok + c_bar_mut->getD(); // expected-error {{incompatible conversion from non owned type 'const owned struct Bar *borrow' to owned type 'owned struct Bar *owned' in member function call}} +} + +safe void test_This_pointer_owned_actual_param(void) { + Bar bar = {.a = 1}; + Bar * owned bar_owned = safe_malloc(bar); + int s_a = bar_owned->getA(); // expected-error {{incompatible conversion from pointer type 'owned struct Bar *owned' to non-pointer type 'owned struct Bar' in member function call}} + int s_b = bar_owned->getB(); // expect error, function getB is error + int s_b2 = bar_owned->getB_2(); // expect error, function getB_2 is error + int s_c = bar_owned->getC(); // expect ok, run ok + int s_c2 = bar_owned->getC_2(); // expect ok, run ok + bar_owned->getD(); // expect ok, run ok +} + +int main() { + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_call/struct_member_function_call/struct_member_function_call.cbs b/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_call/struct_member_function_call/struct_member_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..7a25f7599d37bc1886ce32d5c95620214de44b2d --- /dev/null +++ b/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_call/struct_member_function_call/struct_member_function_call.cbs @@ -0,0 +1,107 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +T* owned safe_malloc(T value); +void free_owned(T* owned p); + +int struct Foo::getA(This this) { + return this.a; +} + +int struct Foo::getA_2(const This this) { + return this.a; +} + +int struct Foo::getB(This* this) { + return this->a; +} + +int struct Foo::getB_2(const This* this) { + return this->a; +} + +int struct Foo::getC(This* borrow this) { + return this->a; +} + +int struct Foo::getC_2(const This* borrow this) { + return this->a; +} + +void struct Foo::getD(This* owned this) { + free_owned(this); +} + +void test_This_actual_param() { + struct Foo foo = {.a = 1}; + const struct Foo foo2 = {.a = 2}; + int a = foo.getA(); // expect ok, run ok + int a2 = foo.getA_2(); + int a3 = foo2.getA(); // expected-error {{incompatible conversion from const type 'const struct Foo' to non-const type 'struct Foo' in member function call}} + int a4 = foo2.getA_2(); + int b = foo.getB(); // expect ok, run ok + int b2 = foo.getB_2(); //expect ok, run ok + int b3 = foo2.getB(); // expected-error {{incompatible conversion from const type 'const struct Foo' to non-const type 'struct Foo *' in member function call}} + int b4 = foo2.getB_2(); + int c = foo.getC(); // expect ok, run ok + int c2 = foo.getC_2(); // expect ok, run ok + foo.getD(); // expected-error {{incompatible conversion from non owned type 'struct Foo' to owned type 'struct Foo *owned' in member function call}} +} + +void test_This_pointer_actual_param() { + struct Foo foo = {.a = 1}; + struct Foo * foo_p = &foo; + int a = foo_p->getA(); // expected-error {{incompatible conversion from pointer type 'struct Foo *' to non-pointer type 'struct Foo' in member function call}} + int b = foo_p->getB(); // expect ok, run ok + int b2 = foo_p->getB_2(); //expect ok, run ok + int c = foo_p->getC(); // expect ok, run ok + int c2 = foo_p->getC_2(); // expect ok, run ok + foo_p->getD(); // expected-error {{incompatible conversion from non owned type 'struct Foo *' to owned type 'struct Foo *owned' in member function call}} +} + +void test_const_This_pointer_actual_param() { + struct Foo foo = {.a = 1}; + const struct Foo * c_foo_p = &foo; + int a = c_foo_p->getA(); // expected-error {{incompatible conversion from pointer type 'const struct Foo *' to non-pointer type 'struct Foo' in member function call}} + int b = c_foo_p->getB(); // expected-error {{incompatible conversion from const type 'const struct Foo *' to non-const type 'struct Foo *' in member function call}} + int b2 = c_foo_p->getB_2(); //expect ok, run ok + int c = c_foo_p->getC(); // expected-error {{incompatible conversion from const type 'const struct Foo *' to non-const type 'struct Foo *borrow' in member function call}} + int c2 = c_foo_p->getC_2(); // expect ok, run ok + c_foo_p->getD(); // expected-error {{incompatible conversion from non owned type 'const struct Foo *' to owned type 'struct Foo *owned' in member function call}} +} + +void test_This_pointer_borrow_actual_param(void) { + struct Foo foo = {.a = 1}; + struct Foo *borrow foo_mut = &mut foo; + int a = foo_mut->getA(); // expected-error {{incompatible conversion from pointer type 'struct Foo *borrow' to non-pointer type 'struct Foo' in member function call}} + int b = foo_mut->getB(); // expect ok, run ok + int b2 = foo_mut->getB_2(); //expect ok, run ok + int c = foo_mut->getC(); // expect ok, run ok + int c2 = foo_mut->getC_2(); // expect ok, run ok + foo_mut->getD(); // expected-error {{incompatible conversion from non owned type 'struct Foo *borrow' to owned type 'struct Foo *owned' in member function call}} +} + +void test_const_This_pointer_borrow_actual_param(void) { + struct Foo foo = {.a = 1}; + const struct Foo *borrow c_foo_mut = &const foo; + int a = c_foo_mut->getA(); // expected-error {{incompatible conversion from pointer type 'const struct Foo *borrow' to non-pointer type 'struct Foo' in member function call}} + int b = c_foo_mut->getB(); // expected-error {{incompatible conversion from const type 'const struct Foo *borrow' to non-const type 'struct Foo *' in member function call}} + int b2 = c_foo_mut->getB_2(); //expect ok, run ok + int c = c_foo_mut->getC(); // expected-error {{incompatible conversion from const type 'const struct Foo *borrow' to non-const type 'struct Foo *borrow' in member function call}} + int c2 = c_foo_mut->getC_2(); // expect ok, run ok + c_foo_mut->getD(); // expected-error {{incompatible conversion from non owned type 'const struct Foo *borrow' to owned type 'struct Foo *owned' in member function call}} +} + +void test_This_pointer_owned_actual_param(void) { + struct Foo foo = {.a = 1}; + struct Foo * owned foo_owned = safe_malloc(foo); + int a = foo_owned->getA(); // expected-error {{incompatible conversion from pointer type 'struct Foo *owned' to non-pointer type 'struct Foo' in member function call}} + int b = foo_owned->getB(); // expect ok, run ok + int b2 = foo_owned->getB_2(); //expect ok, run ok + int c = foo_owned->getC(); // expect ok, run ok + int c2 = foo_owned->getC_2(); // expect ok, run ok + foo_owned->getD(); // expect ok, run ok +} diff --git a/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_call/struct_member_function_call_safe/struct_member_function_call_safe.cbs b/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_call/struct_member_function_call_safe/struct_member_function_call_safe.cbs new file mode 100644 index 0000000000000000000000000000000000000000..35e004ae2bbf756e11daffdd82aa1463041da9be --- /dev/null +++ b/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_call/struct_member_function_call_safe/struct_member_function_call_safe.cbs @@ -0,0 +1,109 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +T* owned safe_malloc(T value); +void free_owned(T* owned p); + +safe int struct Foo::getA(This this) { + return this.a; +} + +safe int struct Foo::getB(This* this) { // expected-error {{unsafe parameter type is forbidden in the safe function}} + return this->a; // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} +} + +safe int struct Foo::getB_2(const This* this) { // expected-error {{unsafe parameter type is forbidden in the safe function}} + return this->a; // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} +} + +safe int struct Foo::getC(This* borrow this) { + this->a = 2; + return this->a; +} + +safe int struct Foo::getC_2(const This* borrow this) { + return this->a; +} + +safe void struct Foo::getD(This* owned this) { + free_owned(this); +} + +safe void test_This_actual_param(void) { + struct Foo foo = {.a = 1}; + int s_a = foo.getA(); // expect ok, run ok + int s_b = foo.getB(); // expect error, function getB is error + int s_b2 = foo.getB_2(); // expect error, function getB_2 is error + int s_c = foo.getC(); // expect ok, run ok + int s_c2 = foo.getC_2(); // expect ok, run ok + foo.getD(); // expected-error {{incompatible conversion from non owned type 'struct Foo' to owned type 'struct Foo *owned' in member function call}} +} + +void test_This_pointer_actual_param() { + struct Foo foo = {.a = 1}; + struct Foo * foo_p = &foo; + safe { + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_a = foo_p->getA(); // expected-error {{incompatible conversion from pointer type 'struct Foo *' to non-pointer type 'struct Foo' in member function call}} + int s_b = foo_p->getB(); // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_b2 = foo_p->getB_2(); // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_c = foo_p->getC(); // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_c2 = foo_p->getC_2(); // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + foo_p->getD(); // expected-error {{incompatible conversion from non owned type 'struct Foo *' to owned type 'struct Foo *owned' in member function call}} + } +} + +void test_const_This_pointer_actual_param() { + struct Foo foo = {.a = 1}; + const struct Foo * c_foo_p = &foo; + safe { + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_a = c_foo_p->getA(); // expected-error {{incompatible conversion from pointer type 'const struct Foo *' to non-pointer type 'struct Foo' in member function call}} + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_b = c_foo_p->getB(); // expected-error {{incompatible conversion from const type 'const struct Foo *' to non-const type 'struct Foo *' in member function call}} + int s_b2 = c_foo_p->getB_2(); // expected-error {{'->' operator used by raw pointer type is forbidden in the safe zone}} + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_c = c_foo_p->getC(); // expected-error {{incompatible conversion from const type 'const struct Foo *' to non-const type 'struct Foo *borrow' in member function call}} + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + int s_c2 = c_foo_p->getC_2(); // expect error, run error + // expected-error@+1 {{'->' operator used by raw pointer type is forbidden in the safe zone}} + c_foo_p->getD(); // expected-error {{incompatible conversion from non owned type 'const struct Foo *' to owned type 'struct Foo *owned' in member function call}} + } +} + +safe void test_This_pointer_borrow_actual_param(void) { + struct Foo foo = {.a = 1}; + struct Foo * borrow foo_mut = &mut foo; + int s_a = foo_mut->getA(); // expected-error {{incompatible conversion from pointer type 'struct Foo *borrow' to non-pointer type 'struct Foo' in member function call}} + int s_b = foo_mut->getB(); // expect error, function getB is error + int s_b2 = foo_mut->getB_2(); // expect error, function getB_2 is error + int s_c = foo_mut->getC(); // expect ok, run ok + int s_c2 = foo_mut->getC_2(); // expect ok, run ok + foo_mut->getD(); // expected-error {{incompatible conversion from non owned type 'struct Foo *borrow' to owned type 'struct Foo *owned' in member function call}} +} + +safe void test_const_This_pointer_borrow_actual_param(void) { + struct Foo foo = {.a = 1}; + const struct Foo *borrow c_foo_mut = &const foo; // incompatible borrow types, cannot cast 'const struct Foo *borrow' + int a = c_foo_mut->getA(); // expected-error {{incompatible conversion from pointer type 'const struct Foo *borrow' to non-pointer type 'struct Foo' in member function call}} + int b = c_foo_mut->getB(); // expected-error {{incompatible conversion from const type 'const struct Foo *borrow' to non-const type 'struct Foo *' in member function call}} + int b2 = c_foo_mut->getB_2(); // expect error, function getB_2 is error + int c = c_foo_mut->getC(); // expected-error {{incompatible conversion from const type 'const struct Foo *borrow' to non-const type 'struct Foo *borrow' in member function call}} + int c2 = c_foo_mut->getC_2(); // expect ok, run ok + c_foo_mut->getD(); // expected-error {{incompatible conversion from non owned type 'const struct Foo *borrow' to owned type 'struct Foo *owned' in member function call}} +} + +safe void test_This_pointer_owned_actual_param(void) { + struct Foo foo = {.a = 1}; + struct Foo * owned foo_owned = safe_malloc(foo); + int s_a = foo_owned->getA(); // expected-error {{incompatible conversion from pointer type 'struct Foo *owned' to non-pointer type 'struct Foo' in member function call}} + int s_b = foo_owned->getB(); // expect error, function getB is error + int s_b2 = foo_owned->getB_2(); // expect error, function getB_2 is error + int s_c = foo_owned->getC(); // expect ok, run ok + int s_c2 = foo_owned->getC_2(); // expect ok, run ok + foo_owned->getD(); // expect ok, run ok +} diff --git a/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_this_parameter_definition/member_function_this_parameter_definition.cbs b/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_this_parameter_definition/member_function_this_parameter_definition.cbs new file mode 100644 index 0000000000000000000000000000000000000000..8690d8c982b34077399de00dc71c7bed206dfb78 --- /dev/null +++ b/clang/test/BSC/Negative/Method/This/this_as_first_parameter/member_function_this_parameter_definition/member_function_this_parameter_definition.cbs @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; +owned struct Bar { +public: + int a; +}; + +int struct Foo::getA(This borrow this) { // expected-error {{borrow type requires a pointer or reference ('This' is invalid)}} + return 0; +} + +int struct Foo::getB(struct Foo borrow this) { // expected-error {{borrow type requires a pointer or reference ('struct Foo' is invalid)}} + return 0; +} + +int struct Foo::getC(const This borrow this) { // expected-error {{borrow type requires a pointer or reference ('This' is invalid)}} + return 0; +} + +int struct Foo::getC_2(const struct Foo borrow this) { // expected-error {{borrow type requires a pointer or reference ('struct Foo' is invalid)}} + return 0; +} +int struct Foo::getD(This owned this) { // expected-error {{owned type requires a pointer, 'owned This' is invalid}} + return 0; +} +int struct Foo::getD_2(struct Foo owned this) { // expected-error {{owned type requires a pointer, 'owned struct Foo' is invalid}} + return 0; +} + + + +// error member functions definition for owned struct +int Bar::getA(const This this) { // ok + return 0; +} + +int Bar::getB(This this) { // ok + return 0; +} + +int Bar::getB_2(Bar this) { // ok + return 0; +} + +int Bar::getC(This owned this) { // expected-error {{owned type requires a pointer, 'owned This' is invalid}} + return 0; +} + +// expected-warning@+1 {{duplicate 'owned' declaration specifier}} +int Bar::getC_2(Bar owned this) { + return 0; +} diff --git a/clang/test/BSC/Negative/Method/Union/union_this_param_check/union_this_param_check.cbs b/clang/test/BSC/Negative/Method/Union/union_this_param_check/union_this_param_check.cbs index ca15a6bcee47a99f6e6563e75c890229bd41edb0..b3a47751da81ba6447ce4fdba052984130b5e598 100644 --- a/clang/test/BSC/Negative/Method/Union/union_this_param_check/union_this_param_check.cbs +++ b/clang/test/BSC/Negative/Method/Union/union_this_param_check/union_this_param_check.cbs @@ -6,6 +6,6 @@ union SimpleUnion { char uc; }; -int union SimpleUnion::getA(union SimpleUnion this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'union SimpleUnion*', but found 'union SimpleUnion'}} +int union SimpleUnion::getA(int this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'This' or 'union SimpleUnion*' or 'union SimpleUnion', but found 'int'}} return 1; } \ No newline at end of file diff --git a/clang/test/BSC/Negative/OwnedStruct/paramlist.cbs b/clang/test/BSC/Negative/OwnedStruct/paramlist.cbs index 1e9e6c8f14c33ce62357db69146d4b14c9145029..99b271727d46ebbe24cc265725f6d483c0f18f70 100644 --- a/clang/test/BSC/Negative/OwnedStruct/paramlist.cbs +++ b/clang/test/BSC/Negative/OwnedStruct/paramlist.cbs @@ -2,10 +2,10 @@ owned struct A { int a; - int f(A this) { return this.a; } // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'owned struct A*', but found 'owned struct A'}} - int g(A this); // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'owned struct A*', but found 'owned struct A'}} + int f(A this) { return this.a; } // expected-error {{memory leak because temporary variable 'this' is owned or indirect owned type, please fix it}} + int g(A this); }; int A::q(int b, A* this); // expected-error {{'this' cannot be the name of a parameter}} -int A::o(int* this); // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'owned struct A*', but found 'int *'}} \ No newline at end of file +int A::o(int* this); // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'This' or 'owned struct A*' or 'owned struct A', but found 'int *'}} \ No newline at end of file diff --git a/clang/test/BSC/Negative/Ownership/Borrow/borrow_field/borrow_field.cbs b/clang/test/BSC/Negative/Ownership/Borrow/borrow_field/borrow_field.cbs index f5d8f49b1104d6c600065abdc72e49aedc0435ea..b47d71415692dd06bd501f2723458c26ab98092d 100644 --- a/clang/test/BSC/Negative/Ownership/Borrow/borrow_field/borrow_field.cbs +++ b/clang/test/BSC/Negative/Ownership/Borrow/borrow_field/borrow_field.cbs @@ -59,7 +59,7 @@ void test() { foo(p1->p); // expected-error {{memory leak because temporary variable 'foo(p1->p)' is owned or indirect owned type, please fix it}} // expected-error@-1 {{borrow type does not allow move ownership}} p2->f1(); // legal - p2->f2(); // expected-error {{incompatible borrow types, cannot cast 'const struct S *borrow' to 'struct S *borrow'}} + p2->f2(); // expected-error {{incompatible conversion from const type 'const struct S *borrow' to non-const type 'struct S *borrow' in member function call}} p1->f1(); // legal p1->f2(); // legal } \ No newline at end of file diff --git a/clang/test/BSC/Negative/ParamCheck/this_not_pointer_type/this_not_pointer_type.cbs b/clang/test/BSC/Negative/ParamCheck/this_not_pointer_type/this_not_pointer_type.cbs index 81a0320594622e64a3801135c2d719a91814555d..41fe7c3afc11938afc44dac19f0f0c8ef9d92e5d 100644 --- a/clang/test/BSC/Negative/ParamCheck/this_not_pointer_type/this_not_pointer_type.cbs +++ b/clang/test/BSC/Negative/ParamCheck/this_not_pointer_type/this_not_pointer_type.cbs @@ -6,8 +6,8 @@ struct S{ struct S struct S::f1(struct S* this) { return this; // expected-error {{returning 'struct S *' from a function with incompatible result type 'struct S'; dereference with *}} } -int struct S::f2(struct S this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'struct S*', but found 'struct S'}} - return this->a; +int struct S::f2(struct S this) { + return this->a; // expected-error {{member reference type 'struct S' is not a pointer; did you mean to use '.'?}} } void test() { struct S s1 = {.a = 42}; diff --git a/clang/test/BSC/Negative/ParamCheck/this_param_type_no_match/this_param_type_no_match.cbs b/clang/test/BSC/Negative/ParamCheck/this_param_type_no_match/this_param_type_no_match.cbs index adcab20e89340da738e3fc1413eae718a2fd9f43..1911bd1c4658023bc3741e68f1be8c3ed9c8e73c 100644 --- a/clang/test/BSC/Negative/ParamCheck/this_param_type_no_match/this_param_type_no_match.cbs +++ b/clang/test/BSC/Negative/ParamCheck/this_param_type_no_match/this_param_type_no_match.cbs @@ -9,7 +9,7 @@ struct Bar { int a; }; -int struct Foo::getBarA(struct Bar* this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'struct Foo*', but found 'struct Bar *'}} +int struct Foo::getBarA(struct Bar* this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'This' or 'struct Foo*' or 'struct Foo', but found 'struct Bar *'}} return this->a; } @@ -19,7 +19,7 @@ enum E { X4 }; -int enum E::getBarA(struct Bar* this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'enum E*', but found 'struct Bar *'}} +int enum E::getBarA(struct Bar* this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'This' or 'enum E*' or 'enum E', but found 'struct Bar *'}} return this->a; } @@ -30,11 +30,11 @@ union SimpleUnion { char uc; }; -int union SimpleUnion::getBarA(struct Bar* this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'union SimpleUnion*', but found 'struct Bar *'}} +int union SimpleUnion::getBarA(struct Bar* this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'This' or 'union SimpleUnion*' or 'union SimpleUnion', but found 'struct Bar *'}} return this->a; } // BuiltinType -int int::getBarA(struct Bar* this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'int*', but found 'struct Bar *'}} +int int::getBarA(struct Bar* this) { // expected-error {{type of parameter 'this' is wrong, expected 'This*' or 'This' or 'int*' or 'int', but found 'struct Bar *'}} return this->a; } \ No newline at end of file diff --git a/clang/test/BSC/Positive/Method/Enum/enum_instance_function/enum_instance_function.cbs b/clang/test/BSC/Positive/Method/Enum/enum_instance_function/enum_instance_function.cbs index 0137a8e4b41d1e21b9cee4d6c0ce89291744ecf8..0df653aae7ad96161394cd0d304e6a863d9f91b9 100644 --- a/clang/test/BSC/Positive/Method/Enum/enum_instance_function/enum_instance_function.cbs +++ b/clang/test/BSC/Positive/Method/Enum/enum_instance_function/enum_instance_function.cbs @@ -14,9 +14,14 @@ int enum E::getA(enum E* this) { return X4; } +int enum E::getB(enum E this) { + return X4; +} + int main() { enum E foo = X3; foo.getA(); + foo.getB(); return 0; } @@ -24,8 +29,13 @@ int main() { // CHECK-NEXT: return X4; // CHECK-NEXT: } +// CHECK: int enum_E_getB(enum E this) { +// CHECK-NEXT: return X4; +// CHECK-NEXT: } + // CHECK: int main(void) { // CHECK: enum E foo = X3; // CHECK-NEXT: enum_E_getA(&foo); +// CHECK-NEXT: enum_E_getB(foo); // CHECK-NEXT: return 0; // CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Positive/Method/Struct/struct_instance_function/struct_instance_function.cbs b/clang/test/BSC/Positive/Method/Struct/struct_instance_function/struct_instance_function.cbs index d89ebf1ca465c8835ab8a7c8790e7acbeae0580a..7a62f20f06a9340b3c6731cf150891f038508295 100644 --- a/clang/test/BSC/Positive/Method/Struct/struct_instance_function/struct_instance_function.cbs +++ b/clang/test/BSC/Positive/Method/Struct/struct_instance_function/struct_instance_function.cbs @@ -11,18 +11,33 @@ struct Foo { int a; }; -int struct Foo::getA(struct Foo* this) { +int struct Foo::getA(This this) { + return this.a; +} + +int struct Foo::getB(This* this) { return this->a; } -// CHECK-L: #line 14 "{{.*}}.cbs" -// CHECK-L-NEXT: int struct_Foo_getA(struct Foo *this) { -// CHECK-L-NEXT: return this->a; -// CHECK-L-NEXT: } +int struct Foo::getC(struct Foo* this) { + return this->a; +} + +int struct Foo::getD(struct Foo this) { + return this.a; +} + +int struct Foo::getE(struct Foo f) { + return f.a; +} int main() { struct Foo foo = {.a = 1}; - foo.getA(); + int a = foo.getA(); + int b = foo.getB(); + int c = foo.getC(); + int d = foo.getD(); + int f = struct Foo::getE(foo); return 0; } @@ -30,13 +45,42 @@ int main() { // CHECK-NEXT: int a; // CHECK-NEXT: }; -// CHECK: int struct_Foo_getA(struct Foo *this) { +// CHECK-L: #line 14 "{{.*}}.cbs" +// CHECK: int struct_Foo_getA(struct Foo this) { +// CHECK-NEXT: return this.a; +// CHECK-NEXT: } +// CHECK-EMPTY: + +// CHECK-L: #line 18 "{{.*}}.cbs" +// CHECK: int struct_Foo_getB(struct Foo *this) { // CHECK-NEXT: return this->a; // CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-L: #line 22 "{{.*}}.cbs" +// CHECK: int struct_Foo_getC(struct Foo *this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } +// CHECK-EMPTY: + +// CHECK-L: #line 26 "{{.*}}.cbs" +// CHECK: int struct_Foo_getD(struct Foo this) { +// CHECK-NEXT: return this.a; +// CHECK-NEXT: } +// CHECK-EMPTY: + +// CHECK-L: #line 30 "{{.*}}.cbs" +// CHECK: int struct_Foo_getE(struct Foo f) { +// CHECK-NEXT: return f.a; +// CHECK-NEXT: } +// CHECK-EMPTY: // CHECK: int main(void) { // CHECK-NEXT: struct Foo foo = {.a = 1}; -// CHECK-NEXT: struct_Foo_getA(&foo); +// CHECK-NEXT: int a = struct_Foo_getA(foo); +// CHECK-NEXT: int b = struct_Foo_getB(&foo); +// CHECK-NEXT: int c = struct_Foo_getC(&foo); +// CHECK-NEXT: int d = struct_Foo_getD(foo); +// CHECK-NEXT: int f = struct_Foo_getE(foo); // CHECK-NEXT: return 0; // CHECK-NEXT: } diff --git a/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_call/generic_member_function_call/generic_member_function_call.cbs b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_call/generic_member_function_call/generic_member_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..f5cf3ba6c6b9b3eebf51253832f54d2499e5b87e --- /dev/null +++ b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_call/generic_member_function_call/generic_member_function_call.cbs @@ -0,0 +1,250 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output +// expected-no-diagnostics + +#include + + +struct Foo { + T a; +}; + +T* owned safe_malloc(T value); +void free_owned(T* owned p); + +T* owned safe_malloc(T value) { + T * p = (T *) malloc( sizeof(T) ); + *p = value; + return (T* owned)p; +} + +void free_owned(T* owned p) { + free( (void *)p ); +} + + +T struct Foo::getA(This this) { + return this.a; +} + +T struct Foo::getA_2(const This this) { + return this.a; +} + +T struct Foo::getB(This* this) { + return this->a; +} + +T struct Foo::getB_2(const This* this) { + return this->a; +} + +T struct Foo::getC(This* borrow this) { + return this->a; +} + +T struct Foo::getC_2(const This* borrow this) { + return this->a; +} + +void struct Foo::getD(This* owned this) { + free_owned>(this); +} + +void test_This_actual_param() { + struct Foo foo = {.a = 1}; + const struct Foo foo2 = {.a = 2}; + int a = foo.getA(); + int a2 = foo.getA_2(); + long a3 = foo2.getA_2(); + int b = foo.getB(); + int b2 = foo.getB_2(); + long b3 = foo2.getB_2(); + int c = foo.getC(); + int c2 = foo.getC_2(); +} + +void test_This_pointer_actual_param() { + struct Foo foo = {.a = 1}; + struct Foo * foo_p = &foo; + int b = foo_p->getB(); + int b2 = foo_p->getB_2(); + int c = foo_p->getC(); + int c2 = foo_p->getC_2(); +} + +void test_const_This_pointer_actual_param() { + struct Foo foo = {.a = 1}; + const struct Foo * c_foo_p = &foo; + long b2 = c_foo_p->getB_2(); + long c2 = c_foo_p->getC_2(); +} + +void test_This_pointer_borrow_actual_param(void) { + struct Foo foo = {.a = 1}; + struct Foo *borrow foo_mut = &mut foo; + int b = foo_mut->getB(); + int b2 = foo_mut->getB_2(); + int c = foo_mut->getC(); + int c2 = foo_mut->getC_2(); +} + +void test_const_This_pointer_borrow_actual_param(void) { + struct Foo foo = {.a = 1}; + const struct Foo *borrow c_foo_mut = &const foo; + long b2 = c_foo_mut->getB_2(); + long c2 = c_foo_mut->getC_2(); +} + +void test_This_pointer_owned_actual_param(void) { + struct Foo foo = {.a = 1}; + struct Foo * owned foo_owned = safe_malloc>(foo); + int b = foo_owned->getB(); + int b2 = foo_owned->getB_2(); + int c = foo_owned->getC(); + int c2 = foo_owned->getC_2(); + foo_owned->getD(); +} + +int main() { + test_This_actual_param(); + test_This_pointer_actual_param(); + test_const_This_pointer_actual_param(); + test_This_pointer_borrow_actual_param(); + test_const_This_pointer_borrow_actual_param(); + test_This_pointer_owned_actual_param(); +} + + +// CHECK: static int struct_Foo_int_getA(struct Foo_int this); + +// CHECK: static int struct_Foo_int_getA_2(const struct Foo_int this); + +// CHECK: static int struct_Foo_int_getB(struct Foo_int *this); + +// CHECK: static int struct_Foo_int_getB_2(const struct Foo_int *this); + +// CHECK: static int struct_Foo_int_getC(struct Foo_int * this); + +// CHECK: static int struct_Foo_int_getC_2(const struct Foo_int * this); + +// CHECK: static void struct_Foo_int_getD(struct Foo_int * this); + +// CHECK: static long struct_Foo_long_getA_2(const struct Foo_long this); + +// CHECK: static long struct_Foo_long_getB_2(const struct Foo_long *this); + +// CHECK: static long struct_Foo_long_getC_2(const struct Foo_long * this); + +// CHECK: static struct Foo_int * safe_malloc_struct_Foo_int(struct Foo_int value); + +// CHECK: static void free_owned_struct_Foo_int(struct Foo_int * p); + +// CHECK: void test_This_actual_param(void) { +// CHECK-NEXT: struct Foo_int foo = {.a = 1}; +// CHECK-NEXT: const struct Foo_long foo2 = {.a = 2}; +// CHECK-NEXT: int a = struct_Foo_int_getA(foo); +// CHECK-NEXT: int a2 = struct_Foo_int_getA_2(foo); +// CHECK-NEXT: long a3 = struct_Foo_long_getA_2(foo2); +// CHECK-NEXT: int b = struct_Foo_int_getB(&foo); +// CHECK-NEXT: int b2 = struct_Foo_int_getB_2(&foo); +// CHECK-NEXT: long b3 = struct_Foo_long_getB_2(&foo2); +// CHECK-NEXT: int c = struct_Foo_int_getC(&foo); +// CHECK-NEXT: int c2 = struct_Foo_int_getC_2(&foo); +// CHECK-NEXT: } + +// CHECK: void test_This_pointer_actual_param(void) { +// CHECK-NEXT: struct Foo_int foo = {.a = 1}; +// CHECK-NEXT: struct Foo_int *foo_p = &foo; +// CHECK-NEXT: int b = struct_Foo_int_getB(foo_p); +// CHECK-NEXT: int b2 = struct_Foo_int_getB_2(foo_p); +// CHECK-NEXT: int c = struct_Foo_int_getC(&*foo_p); +// CHECK-NEXT: int c2 = struct_Foo_int_getC_2(&*foo_p); +// CHECK-NEXT: } + +// CHECK: void test_const_This_pointer_actual_param(void) { +// CHECK-NEXT: struct Foo_long foo = {.a = 1}; +// CHECK-NEXT: const struct Foo_long *c_foo_p = &foo; +// CHECK-NEXT: long b2 = struct_Foo_long_getB_2(c_foo_p); +// CHECK-NEXT: long c2 = struct_Foo_long_getC_2(&*c_foo_p); +// CHECK-NEXT: } + +// CHECK: void test_This_pointer_borrow_actual_param(void) { +// CHECK-NEXT: struct Foo_int foo = {.a = 1}; +// CHECK-NEXT: struct Foo_int * foo_mut = &foo; +// CHECK-NEXT: int b = struct_Foo_int_getB(foo_mut); +// CHECK-NEXT: int b2 = struct_Foo_int_getB_2(foo_mut); +// CHECK-NEXT: int c = struct_Foo_int_getC(foo_mut); +// CHECK-NEXT: int c2 = struct_Foo_int_getC_2(foo_mut); +// CHECK-NEXT: } + +// CHECK: void test_const_This_pointer_borrow_actual_param(void) { +// CHECK-NEXT: struct Foo_long foo = {.a = 1}; +// CHECK-NEXT: const struct Foo_long * c_foo_mut = &foo; +// CHECK-NEXT: long b2 = struct_Foo_long_getB_2(c_foo_mut); +// CHECK-NEXT: long c2 = struct_Foo_long_getC_2(c_foo_mut); +// CHECK-NEXT: } + +// CHECK: void test_This_pointer_owned_actual_param(void) { +// CHECK-NEXT: struct Foo_int foo = {.a = 1}; +// CHECK-NEXT: struct Foo_int * foo_owned = safe_malloc_struct_Foo_int(foo); +// CHECK-NEXT: int b = struct_Foo_int_getB(&*foo_owned); +// CHECK-NEXT: int b2 = struct_Foo_int_getB_2(&*foo_owned); +// CHECK-NEXT: int c = struct_Foo_int_getC(&*foo_owned); +// CHECK-NEXT: int c2 = struct_Foo_int_getC_2(&*foo_owned); +// CHECK-NEXT: struct_Foo_int_getD(foo_owned); +// CHECK-NEXT: } + +// CHECK: static int struct_Foo_int_getA(struct Foo_int this) { +// CHECK-NEXT: return this.a; +// CHECK-NEXT: } + +// CHECK: static int struct_Foo_int_getA_2(const struct Foo_int this) { +// CHECK-NEXT: return this.a; +// CHECK-NEXT: } + +// CHECK: static int struct_Foo_int_getB(struct Foo_int *this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: static int struct_Foo_int_getB_2(const struct Foo_int *this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: static int struct_Foo_int_getC(struct Foo_int * this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: static int struct_Foo_int_getC_2(const struct Foo_int * this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: static void struct_Foo_int_getD(struct Foo_int * this) { +// CHECK-NEXT: free_owned_struct_Foo_int(this); +// CHECK-NEXT: } + +// CHECK: static long struct_Foo_long_getA_2(const struct Foo_long this) { +// CHECK-NEXT: return this.a; +// CHECK-NEXT: } + +// CHECK: static long struct_Foo_long_getB_2(const struct Foo_long *this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: static long struct_Foo_long_getC_2(const struct Foo_long * this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: static struct Foo_int * safe_malloc_struct_Foo_int(struct Foo_int value) { +// CHECK-NEXT: struct Foo_int *p = (struct Foo_int *)malloc(sizeof(struct Foo_int)); +// CHECK-NEXT: *p = value; +// CHECK-NEXT: return (struct Foo_int *)p; +// CHECK-NEXT: } + +// CHECK: static void free_owned_struct_Foo_int(struct Foo_int * p) { +// CHECK-NEXT: free((void *)p); +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_call/struct_member_function_call/struct_member_function_call.cbs b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_call/struct_member_function_call/struct_member_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..e237547629432313529de86ad7d925c1877d70f9 --- /dev/null +++ b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_call/struct_member_function_call/struct_member_function_call.cbs @@ -0,0 +1,203 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output +// expected-no-diagnostics + +#include + +struct Foo { + int a; +}; + +T* owned safe_malloc(T value); +void free_owned(T* owned p); + +T* owned safe_malloc(T value) { + T * p = (T *) malloc( sizeof(T) ); + *p = value; + return (T* owned)p; +} + +void free_owned(T* owned p) { + free( (void *)p ); +} + + +int struct Foo::getA(This this) { + return this.a; +} + +int struct Foo::getA_2(const This this) { + return this.a; +} + +int struct Foo::getB(This* this) { + return this->a; +} + +int struct Foo::getB_2(const This* this) { + return this->a; +} + +int struct Foo::getC(This* borrow this) { + return this->a; +} + +int struct Foo::getC_2(const This* borrow this) { + return this->a; +} + +void struct Foo::getD(This* owned this) { + free_owned(this); +} + +void test_This_actual_param() { + struct Foo foo = {.a = 1}; + const struct Foo foo2 = {.a = 2}; + int a = foo.getA(); + int a2 = foo.getA_2(); + int a3 = foo2.getA_2(); + int b = foo.getB(); + int b2 = foo.getB_2(); + int b3 = foo2.getB_2(); + int c = foo.getC(); + int c2 = foo.getC_2(); +} + +void test_This_pointer_actual_param() { + struct Foo foo = {.a = 1}; + struct Foo * foo_p = &foo; + int b = foo_p->getB(); + int b2 = foo_p->getB_2(); + int c = foo_p->getC(); + int c2 = foo_p->getC_2(); +} + +void test_const_This_pointer_actual_param() { + struct Foo foo = {.a = 1}; + const struct Foo * c_foo_p = &foo; + int b2 = c_foo_p->getB_2(); + int c2 = c_foo_p->getC_2(); +} + +void test_This_pointer_borrow_actual_param(void) { + struct Foo foo = {.a = 1}; + struct Foo *borrow foo_mut = &mut foo; + int b = foo_mut->getB(); + int b2 = foo_mut->getB_2(); + int c = foo_mut->getC(); + int c2 = foo_mut->getC_2(); +} + +void test_const_This_pointer_borrow_actual_param(void) { + struct Foo foo = {.a = 1}; + const struct Foo *borrow c_foo_mut = &const foo; + int b2 = c_foo_mut->getB_2(); + int c2 = c_foo_mut->getC_2(); +} + +void test_This_pointer_owned_actual_param(void) { + struct Foo foo = {.a = 1}; + struct Foo * owned foo_owned = safe_malloc(foo); + int b = foo_owned->getB(); + int b2 = foo_owned->getB_2(); + int c = foo_owned->getC(); + int c2 = foo_owned->getC_2(); + foo_owned->getD(); +} + +int main() { + test_This_actual_param(); + test_This_pointer_actual_param(); + test_const_This_pointer_actual_param(); + test_This_pointer_borrow_actual_param(); + test_const_This_pointer_borrow_actual_param(); + test_This_pointer_owned_actual_param(); +} + + +// CHECK: int struct_Foo_getA(struct Foo this) { +// CHECK-NEXT: return this.a; +// CHECK-NEXT: } + +// CHECK: int struct_Foo_getA_2(const struct Foo this) { +// CHECK-NEXT: return this.a; +// CHECK-NEXT: } + +// CHECK: int struct_Foo_getB(struct Foo *this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: int struct_Foo_getB_2(const struct Foo *this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: int struct_Foo_getC(struct Foo * this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: int struct_Foo_getC_2(const struct Foo * this) { +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: void struct_Foo_getD(struct Foo * this) { +// CHECK-NEXT: free_owned_struct_Foo(this); +// CHECK-NEXT: } + +// CHECK: void test_This_actual_param(void) { +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: const struct Foo foo2 = {.a = 2}; +// CHECK-NEXT: int a = struct_Foo_getA(foo); +// CHECK-NEXT: int a2 = struct_Foo_getA_2(foo); +// CHECK-NEXT: int a3 = struct_Foo_getA_2(foo2); +// CHECK-NEXT: int b = struct_Foo_getB(&foo); +// CHECK-NEXT: int b2 = struct_Foo_getB_2(&foo); +// CHECK-NEXT: int b3 = struct_Foo_getB_2(&foo2); +// CHECK-NEXT: int c = struct_Foo_getC(&foo); +// CHECK-NEXT: int c2 = struct_Foo_getC_2(&foo); +// CHECK-NEXT: } + +// CHECK: void test_This_pointer_actual_param(void) { +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: struct Foo *foo_p = &foo; +// CHECK-NEXT: int b = struct_Foo_getB(foo_p); +// CHECK-NEXT: int b2 = struct_Foo_getB_2(foo_p); +// CHECK-NEXT: int c = struct_Foo_getC(&*foo_p); +// CHECK-NEXT: int c2 = struct_Foo_getC_2(&*foo_p); +// CHECK-NEXT: } + +// CHECK: void test_const_This_pointer_actual_param(void) { +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: const struct Foo *c_foo_p = &foo; +// CHECK-NEXT: int b2 = struct_Foo_getB_2(c_foo_p); +// CHECK-NEXT: int c2 = struct_Foo_getC_2(&*c_foo_p); +// CHECK-NEXT: } + +// CHECK: void test_This_pointer_borrow_actual_param(void) { +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: struct Foo * foo_mut = &foo; +// CHECK-NEXT: int b = struct_Foo_getB(foo_mut); +// CHECK-NEXT: int b2 = struct_Foo_getB_2(foo_mut); +// CHECK-NEXT: int c = struct_Foo_getC(foo_mut); +// CHECK-NEXT: int c2 = struct_Foo_getC_2(foo_mut); +// CHECK-NEXT: } + +// CHECK: void test_const_This_pointer_borrow_actual_param(void) { +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: const struct Foo * c_foo_mut = &foo; +// CHECK-NEXT: int b2 = struct_Foo_getB_2(c_foo_mut); +// CHECK-NEXT: int c2 = struct_Foo_getC_2(c_foo_mut); +// CHECK-NEXT: } + +// CHECK: void test_This_pointer_owned_actual_param(void) { +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: struct Foo * foo_owned = safe_malloc_struct_Foo(foo); +// CHECK-NEXT: int b = struct_Foo_getB(&*foo_owned); +// CHECK-NEXT: int b2 = struct_Foo_getB_2(&*foo_owned); +// CHECK-NEXT: int c = struct_Foo_getC(&*foo_owned); +// CHECK-NEXT: int c2 = struct_Foo_getC_2(&*foo_owned); +// CHECK-NEXT: struct_Foo_getD(foo_owned); +// CHECK-NEXT: } diff --git a/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/member_function_pointer_reborrow_ast/member_function_pointer_reborrow_ast.cbs b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/member_function_pointer_reborrow_ast/member_function_pointer_reborrow_ast.cbs new file mode 100644 index 0000000000000000000000000000000000000000..56c70911044837c3464112688ac0a14a90da8ca4 --- /dev/null +++ b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/member_function_pointer_reborrow_ast/member_function_pointer_reborrow_ast.cbs @@ -0,0 +1,119 @@ +// Test without serialization: +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ast-dump %s \ +// RUN: | FileCheck --strict-whitespace %s + +struct Foo { + int a; +}; + +T* owned safe_malloc(T value); +void free_owned(T* owned p); + + +int struct Foo::getB(This* this) { + this->a = 3; + return this->a; +} + +int struct Foo::getB_2(const This* this) { + return this->a; +} + +safe int struct Foo::getC(This* borrow this) { + this->a = 2; + return this->a; +} + +safe int struct Foo::getC_2(const This* borrow this) { + return this->a; +} + +safe void struct Foo::getD(This* owned this) { + free_owned(this); +} + +void test_non_pointer_This_call_reborrow() { + struct Foo foo = {.a = 1}; + safe { + int c = foo.getC(); + int c_2 = foo.getC_2(); + } +} +// CHECK: DeclStmt 0x{{[^ ]*}} +// CHECK-NEXT: VarDecl 0x{{[^ ]*}} col:9 c 'int' cinit +// CHECK-NEXT: CallExpr 0x{{[^ ]*}} 'int' +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'int (*)(struct Foo *borrow)' safe +// CHECK-NEXT: MemberExpr 0x{{[^ ]*}} 'int (struct Foo *borrow)' safe lvalue .getC +// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'struct Foo':'struct Foo' lvalue Var 0x{{[^ ]*}} 'foo' 'struct Foo':'struct Foo' +// CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <, col:13> 'struct Foo *borrow' prefix '&mut' cannot overflow +// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'struct Foo':'struct Foo' lvalue Var 0x{{[^ ]*}} 'foo' 'struct Foo':'struct Foo' + +// CHECK: DeclStmt 0x{{[^ ]*}} +// CHECK-NEXT: VarDecl 0x{{[^ ]*}} col:9 c_2 'int' cinit +// CHECK-NEXT: CallExpr 0x{{[^ ]*}} 'int' +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'int (*)(const struct Foo *borrow)' safe +// CHECK-NEXT: MemberExpr 0x{{[^ ]*}} 'int (const struct Foo *borrow)' safe lvalue .getC_2 0x{{[^ ]*}} +// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'struct Foo':'struct Foo' lvalue Var 0x{{[^ ]*}} 'foo' 'struct Foo':'struct Foo' +// CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <, col:15> 'const struct Foo *borrow' prefix '&const' cannot overflow +// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'struct Foo':'struct Foo' lvalue Var 0x{{[^ ]*}} 'foo' 'struct Foo':'struct Foo' + + +void test_const_raw_pointer_call_reborrow() { + struct Foo foo = {.a = 1}; + const struct Foo* c_foo_p = &foo; + int b_2 = c_foo_p->getB_2(); + int c_2 = c_foo_p->getC_2(); +} +// CHECK: DeclStmt 0x{{[^ ]*}} +// CHECK-NEXT: VarDecl 0x{{[^ ]*}} col:7 b_2 'int' cinit +// CHECK-NEXT: CallExpr 0x{{[^ ]*}} 'int' +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'int (*)(const struct Foo *)' +// CHECK-NEXT: MemberExpr 0x{{[^ ]*}} 'int (const struct Foo *)' lvalue ->getB_2 0x{{[^ ]*}} +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'const struct Foo *' +// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'const struct Foo *' lvalue Var 0x{{[^ ]*}} 'c_foo_p' 'const struct Foo *' +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'const struct Foo *' +// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'const struct Foo *' lvalue Var 0x{{[^ ]*}} 'c_foo_p' 'const struct Foo *' + +// CHECK: DeclStmt 0x{{[^ ]*}} +// CHECK-NEXT: VarDecl 0x{{[^ ]*}} col:7 c_2 'int' cinit +// CHECK-NEXT: CallExpr 0x{{[^ ]*}} 'int' +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'int (*)(const struct Foo *borrow)' safe +// CHECK-NEXT: MemberExpr 0x{{[^ ]*}} 'int (const struct Foo *borrow)' safe lvalue ->getC_2 0x{{[^ ]*}} +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'const struct Foo *' +// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'const struct Foo *' lvalue Var 0x{{[^ ]*}} 'c_foo_p' 'const struct Foo *' +// CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <, col:13> 'const struct Foo *borrow' prefix '&const *' cannot overflow +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'const struct Foo *' +// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'const struct Foo *' lvalue Var 0x{{[^ ]*}} 'c_foo_p' 'const struct Foo *' + +void test_owned_pointer_call_reborrow() { + struct Foo foo = {.a = 1}; + struct Foo * owned foo_owned = safe_malloc(foo); + int b = foo_owned->getB(); + int b_2 = foo_owned->getB_2(); + safe { + int c = foo_owned->getC(); + int c_2 = foo_owned->getC_2(); + foo_owned->getD(); + } +} +// CHECK: DeclStmt 0x{{[^ ]*}} +// CHECK-NEXT: VarDecl 0x{{[^ ]*}} col:9 c 'int' cinit +// CHECK-NEXT: CallExpr 0x{{[^ ]*}} 'int' +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'int (*)(struct Foo *borrow)' safe +// CHECK-NEXT: MemberExpr 0x{{[^ ]*}} 'int (struct Foo *borrow)' safe lvalue ->getC 0x{{[^ ]*}} +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'struct Foo *owned' +// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'struct Foo *owned' lvalue Var 0x{{[^ ]*}} 'foo_owned' 'struct Foo *owned' +// CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <, col:13> 'struct Foo *borrow' prefix '&mut *' cannot overflow +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'struct Foo *owned' +// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'struct Foo *owned' lvalue Var 0x{{[^ ]*}} 'foo_owned' 'struct Foo *owned' + +// CHECK: DeclStmt 0x{{[^ ]*}} +// CHECK-NEXT: VarDecl 0x{{[^ ]*}} col:9 c_2 'int' cinit +// CHECK-NEXT: CallExpr 0x{{[^ ]*}} 'int' +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'int (*)(const struct Foo *borrow)' safe +// CHECK-NEXT: MemberExpr 0x{{[^ ]*}} 'int (const struct Foo *borrow)' safe lvalue ->getC_2 0x{{[^ ]*}} +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'struct Foo *owned' +// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'struct Foo *owned' lvalue Var 0x{{[^ ]*}} 'foo_owned' 'struct Foo *owned' +// CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <, col:15> 'const struct Foo *borrow' prefix '&const *' cannot overflow +// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} 'struct Foo *owned' +// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'struct Foo *owned' lvalue Var 0x{{[^ ]*}} 'foo_owned' 'struct Foo *owned' diff --git a/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/owned_struct_member_function_pointer_reborrow/expected.txt b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/owned_struct_member_function_pointer_reborrow/expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..5f469cf725da0051047804f3cad17a42eb4c042c --- /dev/null +++ b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/owned_struct_member_function_pointer_reborrow/expected.txt @@ -0,0 +1,21 @@ +test_non_pointer_This_call_reborrow: +this->a in getB: 3 +this->a in getB_2: 3 +this->a in getC: 2 +this->a in getC_2: 2 +this->a in test: 2 +test_raw_pointer_call_reborrow: +this->a in getB: 3 +this->a in getB_2: 3 +this->a in getC: 2 +this->a in getC_2: 2 +this->a in test: 2 +test_const_raw_pointer_call_reborrow: +this->a in getB_2: 1 +this->a in getC_2: 1 +this->a in test: 1 +test_owned_pointer_call_reborrow: +this->a in getB: 3 +this->a in getB_2: 3 +this->a in getC: 2 +this->a in getC_2: 2 diff --git a/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/owned_struct_member_function_pointer_reborrow/owned_struct_member_function_pointer_reborrow.cbs b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/owned_struct_member_function_pointer_reborrow/owned_struct_member_function_pointer_reborrow.cbs new file mode 100644 index 0000000000000000000000000000000000000000..74e71d7e76f72e164af86d9ed71335b812047d77 --- /dev/null +++ b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/owned_struct_member_function_pointer_reborrow/owned_struct_member_function_pointer_reborrow.cbs @@ -0,0 +1,200 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output +// expected-no-diagnostics + +#include +#include + +owned struct Bar { +public: + int a; +}; + +T* owned safe_malloc(T value); +void free_owned(T* owned p); + +T* owned safe_malloc(T value) { + T * p = (T *) malloc( sizeof(T) ); + *p = value; + return (T* owned)p; +} + +void free_owned(T* owned p) { + free( (void *)p ); +} + +int Bar::getB(This* this) { + this->a = 3; + printf("this->a in getB: %d\n", this->a); + return this->a; +} + +int Bar::getB_2(const This* this) { + printf("this->a in getB_2: %d\n", this->a); + return this->a; +} + +safe int Bar::getC(This* borrow this) { + this->a = 2; + unsafe { + printf("this->a in getC: %d\n", this->a); + } + return this->a; +} + +safe int Bar::getC_2(const This* borrow this) { + unsafe { + printf("this->a in getC_2: %d\n", this->a); + } + return this->a; +} + +safe void Bar::getD(This* owned this) { + free_owned(this); +} + +void test_non_pointer_This_call_reborrow() { + printf("test_non_pointer_This_call_reborrow:\n"); + Bar foo = {.a = 1}; + int b = foo.getB(); + int b_2 = foo.getB_2(); + safe { + int c = foo.getC(); + int c_2 = foo.getC_2(); + } + printf("this->a in test: %d\n", foo.a); +} + +void test_raw_pointer_call_reborrow() { + printf("test_raw_pointer_call_reborrow:\n"); + Bar foo = {.a = 1}; + Bar * foo_p = &foo; + int b = foo_p->getB(); + int b_2 = foo_p->getB_2(); + int c = foo_p->getC(); + int c_2 = foo_p->getC_2(); + printf("this->a in test: %d\n", foo.a); +} + +void test_const_raw_pointer_call_reborrow() { + printf("test_const_raw_pointer_call_reborrow:\n"); + Bar foo = {.a = 1}; + const Bar* c_foo_p = &foo; + int b_2 = c_foo_p->getB_2(); + int c_2 = c_foo_p->getC_2(); + printf("this->a in test: %d\n", foo.a); +} + +void test_owned_pointer_call_reborrow() { + printf("test_owned_pointer_call_reborrow:\n"); + Bar foo = {.a = 1}; + Bar * owned foo_owned = safe_malloc(foo); + int b = foo_owned->getB(); + int b_2 = foo_owned->getB_2(); + safe { + int c = foo_owned->getC(); + int c_2 = foo_owned->getC_2(); + foo_owned->getD(); + } +} + +int main() { + test_non_pointer_This_call_reborrow(); + test_raw_pointer_call_reborrow(); + test_const_raw_pointer_call_reborrow(); + test_owned_pointer_call_reborrow(); + return 0; +} + + +// CHECK: int struct_Bar_getB( struct Bar *this) { +// CHECK-NEXT: this->a = 3; +// CHECK-NEXT: printf("this->a in getB: %d\n", this->a); +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: int struct_Bar_getB_2(const struct Bar *this) { +// CHECK-NEXT: printf("this->a in getB_2: %d\n", this->a); +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: int struct_Bar_getC( struct Bar * this) { +// CHECK-NEXT: this->a = 2; +// CHECK-NEXT: { +// CHECK-NEXT: printf("this->a in getC: %d\n", this->a); +// CHECK-NEXT: } +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: int struct_Bar_getC_2(const struct Bar * this) { +// CHECK-NEXT: { +// CHECK-NEXT: printf("this->a in getC_2: %d\n", this->a); +// CHECK-NEXT: } +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: void struct_Bar_getD( struct Bar * this) { +// CHECK-NEXT: free_owned_struct_Bar(this); +// CHECK-NEXT: } + +// CHECK: void test_non_pointer_This_call_reborrow(void) { +// CHECK-NEXT: printf("test_non_pointer_This_call_reborrow:\n"); +// CHECK-NEXT: struct Bar foo = {.a = 1}; +// CHECK-NEXT: _Bool foo_is_moved = 0; +// CHECK-NEXT: int b = struct_Bar_getB(&foo); +// CHECK-NEXT: int b_2 = struct_Bar_getB_2(&foo); +// CHECK-NEXT: { +// CHECK-NEXT: int c = struct_Bar_getC(&foo); +// CHECK-NEXT: int c_2 = struct_Bar_getC_2(&foo); +// CHECK-NEXT: } +// CHECK-NEXT: printf("this->a in test: %d\n", foo.a); +// CHECK-NEXT: if (!foo_is_moved) +// CHECK-NEXT: struct_Bar_D(foo); +// CHECK-NEXT: } + +// CHECK: void test_raw_pointer_call_reborrow(void) { +// CHECK-NEXT: printf("test_raw_pointer_call_reborrow:\n"); +// CHECK-NEXT: struct Bar foo = {.a = 1}; +// CHECK-NEXT: _Bool foo_is_moved = 0; +// CHECK-NEXT: struct Bar *foo_p = &foo; +// CHECK-NEXT: int b = struct_Bar_getB(foo_p); +// CHECK-NEXT: int b_2 = struct_Bar_getB_2(foo_p); +// CHECK-NEXT: int c = struct_Bar_getC(&*foo_p); +// CHECK-NEXT: int c_2 = struct_Bar_getC_2(&*foo_p); +// CHECK-NEXT: printf("this->a in test: %d\n", foo.a); +// CHECK-NEXT: if (!foo_is_moved) +// CHECK-NEXT: struct_Bar_D(foo); +// CHECK-NEXT: } + +// CHECK: void test_const_raw_pointer_call_reborrow(void) { +// CHECK-NEXT: printf("test_const_raw_pointer_call_reborrow:\n"); +// CHECK-NEXT: struct Bar foo = {.a = 1}; +// CHECK-NEXT: _Bool foo_is_moved = 0; +// CHECK-NEXT: const struct Bar *c_foo_p = &foo; +// CHECK-NEXT: int b_2 = struct_Bar_getB_2(c_foo_p); +// CHECK-NEXT: int c_2 = struct_Bar_getC_2(&*c_foo_p); +// CHECK-NEXT: printf("this->a in test: %d\n", foo.a); +// CHECK-NEXT: if (!foo_is_moved) +// CHECK-NEXT: struct_Bar_D(foo); +// CHECK-NEXT: } + +// CHECK: void test_owned_pointer_call_reborrow(void) { +// CHECK-NEXT: printf("test_owned_pointer_call_reborrow:\n"); +// CHECK-NEXT: struct Bar foo = {.a = 1}; +// CHECK-NEXT: _Bool foo_is_moved = 0; +// CHECK-NEXT: struct Bar * foo_owned = safe_malloc_struct_Bar(foo); +// CHECK-NEXT: foo_is_moved = 1; +// CHECK-NEXT: int b = struct_Bar_getB(&*foo_owned); +// CHECK-NEXT: int b_2 = struct_Bar_getB_2(&*foo_owned); +// CHECK-NEXT: { +// CHECK-NEXT: int c = struct_Bar_getC(&*foo_owned); +// CHECK-NEXT: int c_2 = struct_Bar_getC_2(&*foo_owned); +// CHECK-NEXT: struct_Bar_getD(foo_owned); +// CHECK-NEXT: } +// CHECK-NEXT: if (!foo_is_moved) +// CHECK-NEXT: struct_Bar_D(foo); +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/struct_member_function_pointer_reborrow/expected.txt b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/struct_member_function_pointer_reborrow/expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..74675653d7b09a906f46f2fd4057b9d43b74e6e8 --- /dev/null +++ b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/struct_member_function_pointer_reborrow/expected.txt @@ -0,0 +1,26 @@ +test_non_pointer_This_call_reborrow: +this->a in getB: 3 +this->a in getB_2: 3 +this->a in getC: 2 +this->a in getC_2: 2 +this->a in test: 2 +test_raw_pointer_call_reborrow: +this->a in getB: 3 +this->a in getB_2: 3 +this->a in getC: 2 +this->a in getC_2: 2 +this->a in test: 2 +test_const_raw_pointer_call_reborrow: +this->a in getB_2: 1 +this->a in getC_2: 1 +this->a in test: 1 +test_borrow_pointer_call_reborrow: +this->a in getB: 3 +this->a in getC: 2 +this->a in test: 2 +test_owned_pointer_call_reborrow: +this->a in getB: 3 +this->a in getB_2: 3 +this->a in getC: 2 +this->a in getC_2: 2 +this->a in test: 1 diff --git a/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/struct_member_function_pointer_reborrow/struct_member_function_pointer_reborrow.cbs b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/struct_member_function_pointer_reborrow/struct_member_function_pointer_reborrow.cbs new file mode 100644 index 0000000000000000000000000000000000000000..dc07fd416eaf856b510d179f2e102c4f2d2c9ff3 --- /dev/null +++ b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_pointer_reborrow/struct_member_function_pointer_reborrow/struct_member_function_pointer_reborrow.cbs @@ -0,0 +1,206 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: FileCheck --input-file=%t-rw.c %s +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output +// expected-no-diagnostics + +#include +#include + +struct Foo { + int a; +}; + +T* owned safe_malloc(T value); +void free_owned(T* owned p); + +T* owned safe_malloc(T value) { + T * p = (T *) malloc( sizeof(T) ); + *p = value; + return (T* owned)p; +} + +void free_owned(T* owned p) { + free( (void *)p ); +} + +int struct Foo::getB(This* this) { + this->a = 3; + printf("this->a in getB: %d\n", this->a); + return this->a; +} + +int struct Foo::getB_2(const This* this) { + printf("this->a in getB_2: %d\n", this->a); + return this->a; +} + +safe int struct Foo::getC(This* borrow this) { + this->a = 2; + unsafe { + printf("this->a in getC: %d\n", this->a); + } + return this->a; +} + +safe int struct Foo::getC_2(const This* borrow this) { + unsafe { + printf("this->a in getC_2: %d\n", this->a); + } + return this->a; +} + +safe void struct Foo::getD(This* owned this) { + free_owned(this); +} + +void test_non_pointer_This_call_reborrow() { + printf("test_non_pointer_This_call_reborrow:\n"); + struct Foo foo = {.a = 1}; + int b = foo.getB(); + int b_2 = foo.getB_2(); + safe { + int c = foo.getC(); + int c_2 = foo.getC_2(); + } + printf("this->a in test: %d\n", foo.a); +} + +void test_raw_pointer_call_reborrow() { + printf("test_raw_pointer_call_reborrow:\n"); + struct Foo foo = {.a = 1}; + struct Foo * foo_p = &foo; + int b = foo_p->getB(); + int b_2 = foo_p->getB_2(); + int c = foo_p->getC(); + int c_2 = foo_p->getC_2(); + printf("this->a in test: %d\n", foo.a); +} + +void test_const_raw_pointer_call_reborrow() { + printf("test_const_raw_pointer_call_reborrow:\n"); + struct Foo foo = {.a = 1}; + const struct Foo* c_foo_p = &foo; + int b_2 = c_foo_p->getB_2(); + int c_2 = c_foo_p->getC_2(); + printf("this->a in test: %d\n", foo.a); +} + +void test_borrow_pointer_call_reborrow() { + printf("test_borrow_pointer_call_reborrow:\n"); + struct Foo foo = {.a = 1}; + struct Foo* borrow c_foo_mut = &mut foo; + int b_2 = c_foo_mut->getB(); + int c_2 = c_foo_mut->getC(); + printf("this->a in test: %d\n", foo.a); +} + +void test_owned_pointer_call_reborrow() { + printf("test_owned_pointer_call_reborrow:\n"); + struct Foo foo = {.a = 1}; + struct Foo * owned foo_owned = safe_malloc(foo); + int b = foo_owned->getB(); + int b_2 = foo_owned->getB_2(); + safe { + int c = foo_owned->getC(); + int c_2 = foo_owned->getC_2(); + foo_owned->getD(); + } + printf("this->a in test: %d\n", foo.a); +} + +int main() { + test_non_pointer_This_call_reborrow(); + test_raw_pointer_call_reborrow(); + test_const_raw_pointer_call_reborrow(); + test_borrow_pointer_call_reborrow(); + test_owned_pointer_call_reborrow(); + return 0; +} + +// CHECK: int struct_Foo_getB(struct Foo *this) { +// CHECK-NEXT: this->a = 3; +// CHECK-NEXT: printf("this->a in getB: %d\n", this->a); +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: int struct_Foo_getB_2(const struct Foo *this) { +// CHECK-NEXT: printf("this->a in getB_2: %d\n", this->a); +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: int struct_Foo_getC(struct Foo * this) { +// CHECK-NEXT: this->a = 2; +// CHECK-NEXT: { +// CHECK-NEXT: printf("this->a in getC: %d\n", this->a); +// CHECK-NEXT: } +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: int struct_Foo_getC_2(const struct Foo * this) { +// CHECK-NEXT: { +// CHECK-NEXT: printf("this->a in getC_2: %d\n", this->a); +// CHECK-NEXT: } +// CHECK-NEXT: return this->a; +// CHECK-NEXT: } + +// CHECK: void struct_Foo_getD(struct Foo * this) { +// CHECK-NEXT: free_owned_struct_Foo(this); +// CHECK-NEXT: } + +// CHECK: void test_non_pointer_This_call_reborrow(void) { +// CHECK-NEXT: printf("test_non_pointer_This_call_reborrow:\n"); +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: int b = struct_Foo_getB(&foo); +// CHECK-NEXT: int b_2 = struct_Foo_getB_2(&foo); +// CHECK-NEXT: { +// CHECK-NEXT: int c = struct_Foo_getC(&foo); +// CHECK-NEXT: int c_2 = struct_Foo_getC_2(&foo); +// CHECK-NEXT: } +// CHECK-NEXT: printf("this->a in test: %d\n", foo.a); +// CHECK-NEXT: } + +// CHECK: void test_raw_pointer_call_reborrow(void) { +// CHECK-NEXT: printf("test_raw_pointer_call_reborrow:\n"); +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: struct Foo *foo_p = &foo; +// CHECK-NEXT: int b = struct_Foo_getB(foo_p); +// CHECK-NEXT: int b_2 = struct_Foo_getB_2(foo_p); +// CHECK-NEXT: int c = struct_Foo_getC(&*foo_p); +// CHECK-NEXT: int c_2 = struct_Foo_getC_2(&*foo_p); +// CHECK-NEXT: printf("this->a in test: %d\n", foo.a); +// CHECK-NEXT: } + +// CHECK: void test_const_raw_pointer_call_reborrow(void) { +// CHECK-NEXT: printf("test_const_raw_pointer_call_reborrow:\n"); +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: const struct Foo *c_foo_p = &foo; +// CHECK-NEXT: int b_2 = struct_Foo_getB_2(c_foo_p); +// CHECK-NEXT: int c_2 = struct_Foo_getC_2(&*c_foo_p); +// CHECK-NEXT: printf("this->a in test: %d\n", foo.a); +// CHECK-NEXT: } + +// CHECK: void test_borrow_pointer_call_reborrow(void) { +// CHECK-NEXT: printf("test_borrow_pointer_call_reborrow:\n"); +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: struct Foo * c_foo_mut = &foo; +// CHECK-NEXT: int b_2 = struct_Foo_getB(c_foo_mut); +// CHECK-NEXT: int c_2 = struct_Foo_getC(c_foo_mut); +// CHECK-NEXT: printf("this->a in test: %d\n", foo.a); +// CHECK-NEXT: } + +// CHECK: void test_owned_pointer_call_reborrow(void) { +// CHECK-NEXT: printf("test_owned_pointer_call_reborrow:\n"); +// CHECK-NEXT: struct Foo foo = {.a = 1}; +// CHECK-NEXT: struct Foo * foo_owned = safe_malloc_struct_Foo(foo); +// CHECK-NEXT: int b = struct_Foo_getB(&*foo_owned); +// CHECK-NEXT: int b_2 = struct_Foo_getB_2(&*foo_owned); +// CHECK-NEXT: { +// CHECK-NEXT: int c = struct_Foo_getC(&*foo_owned); +// CHECK-NEXT: int c_2 = struct_Foo_getC_2(&*foo_owned); +// CHECK-NEXT: struct_Foo_getD(foo_owned); +// CHECK-NEXT: } +// CHECK-NEXT: printf("this->a in test: %d\n", foo.a); +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_this_parameter_definition/member_function_this_parameter_definition.cbs b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_this_parameter_definition/member_function_this_parameter_definition.cbs new file mode 100644 index 0000000000000000000000000000000000000000..722990ba3a9ea739eaec3a076274159538b005fb --- /dev/null +++ b/clang/test/BSC/Positive/Method/This/this_as_first_parameter/member_function_this_parameter_definition/member_function_this_parameter_definition.cbs @@ -0,0 +1,107 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +struct Foo { + int a; +}; +owned struct Bar { +public: + int a; +}; + +//ok member functions definition for struct +int struct Foo::getA(This this) { + return this.a; +} +int struct Foo::getA_2(struct Foo this) { + return this.a; +} +int struct Foo::getB(This* this) { + return this->a; +} +int struct Foo::getB_2(struct Foo* this) { + return this->a; +} +int struct Foo::getC(const This* this) { + return this->a; +} +int struct Foo::getC_2(const struct Foo* this) { + return this->a; +} +int struct Foo::getD(This* borrow this) { + return this->a; +} +int struct Foo::getD_2(struct Foo* borrow this) { + return this->a; +} +int struct Foo::getE(const This* borrow this) { + return this->a; +} +int struct Foo::getE_2(const struct Foo* borrow this) { + return this->a; +} +struct Foo* owned struct Foo::getF(This* owned this) { + return this; +} +struct Foo* owned struct Foo::getF_2(struct Foo* owned this) { + return this; +} + +int struct Foo::getG(const This this) { + return this.a; +} +struct Foo* const struct Foo::getG_2(This* const this) { + return this; +} +const struct Foo* owned struct Foo::getH(const This* owned this) { + return this; +} + +Bar Bar::getA_0(const This this) { + return this; +} + +const Bar* owned Bar::getD_0(const This* owned this) { + return this; +} +Bar* const Bar::getE_0(This* const this) { + return this; +} + +// ok member functions definition for owned struct +Bar Bar::getA(This this) { + return this; +} +Bar Bar::getA_2(Bar this) { + return this; +} +int Bar::getB(This* this) { + return this->a; +} +int Bar::getB_2(Bar* this) { + return this->a; +} +int Bar::getC(const This* this) { + return this->a; +} +int Bar::getC_2(const Bar* this) { + return this->a; +} +int Bar::getD(This* borrow this) { + return this->a; +} +int Bar::getD_2(Bar* borrow this) { + return this->a; +} +int Bar::getE(const This* borrow this) { + return this->a; +} +int Bar::getE_2(const Bar* borrow this) { + return this->a; +} +Bar* owned Bar::getF(This* owned this) { + return this; +} +Bar* owned Bar::getF_2(Bar* owned this) { + return this; +} diff --git a/clang/test/BSC/Positive/Method/This/use_This_as_BSCMethod_parameter/expected.txt b/clang/test/BSC/Positive/Method/This/use_This_as_BSCMethod_parameter/expected.txt index 705df83381e3cea958ee0df4bfa4947c9bfcfab0..08c96bc841003a2f9902b78731c59e50138027b6 100644 --- a/clang/test/BSC/Positive/Method/This/use_This_as_BSCMethod_parameter/expected.txt +++ b/clang/test/BSC/Positive/Method/This/use_This_as_BSCMethod_parameter/expected.txt @@ -1,4 +1,7 @@ 9 +9 +14 14 19 +19 diff --git a/clang/test/BSC/Positive/Method/This/use_This_as_BSCMethod_parameter/use_This_as_BSCMethod_parameter.cbs b/clang/test/BSC/Positive/Method/This/use_This_as_BSCMethod_parameter/use_This_as_BSCMethod_parameter.cbs index ce0fce838d437b052fbe93cb15057ce208b818fe..995c80d170d332dcc19d926af4f6b95c192ba91d 100644 --- a/clang/test/BSC/Positive/Method/This/use_This_as_BSCMethod_parameter/use_This_as_BSCMethod_parameter.cbs +++ b/clang/test/BSC/Positive/Method/This/use_This_as_BSCMethod_parameter/use_This_as_BSCMethod_parameter.cbs @@ -16,6 +16,9 @@ void S1::f(This* this, int b) { void struct S::dump(This* this) { printf("%d\n", this->a); } +void struct S::dump2(This this) { + printf("%d\n", this.a); +} void int::f(This* this, int b) { *this = *this + b; @@ -23,6 +26,10 @@ void int::f(This* this, int b) { void int::dump(This* this) { printf("%d\n", *this); } +void int::dump2(This this) { + printf("%d\n", this); +} + void int::bar(const This* const this) { } // CHECK: void int_bar(const int *const this) { @@ -37,6 +44,9 @@ void struct G::f(This* this, int b) { void struct G::dump(This* this) { printf("%d\n", this->d); } +void struct G::dump2(This this) { + printf("%d\n", this.d); +} void struct G::bar(const This* const this) { } // CHECK: static void struct_G_int_bar(const struct G_int *const this) { @@ -46,14 +56,17 @@ int main() { struct S s = {.a = 5}; s.f(4); s.dump(); // print 9 + s.dump2(); // print 9 int c = 10; c.f(4); c.dump(); // print 14 + c.dump2(); // print 14 struct G g = {.d = 15}; g.f(4); g.dump(); // print 19 + g.dump2(); // print 19 g.bar(); return 0; diff --git a/clang/test/BSC/Positive/Method/Union/union_instance_function_declaration/union_instance_function_declaration.cbs b/clang/test/BSC/Positive/Method/Union/union_instance_function_declaration/union_instance_function_declaration.cbs index 5b1277c6947da19df89aef4cb5c516fd10349bac..b5eb48d7e961cbf18eae74bfdd8ec24fc5e7a1c1 100644 --- a/clang/test/BSC/Positive/Method/Union/union_instance_function_declaration/union_instance_function_declaration.cbs +++ b/clang/test/BSC/Positive/Method/Union/union_instance_function_declaration/union_instance_function_declaration.cbs @@ -13,9 +13,14 @@ union SimpleUnion { int union SimpleUnion::getA(union SimpleUnion* this); +int union SimpleUnion::getB(union SimpleUnion this) { + return 1; +} + int main() { union SimpleUnion u = {.ui = 1}; u.getA(); + u.getB(); return 0; } @@ -24,5 +29,7 @@ int union SimpleUnion::getA(union SimpleUnion * this) { } // CHECK: int union_SimpleUnion_getA(union SimpleUnion *this); +// CHECK: int union_SimpleUnion_getB(union SimpleUnion this) { + // CHECK: union_SimpleUnion_getA(&u); // CHECK: int union_SimpleUnion_getA(union SimpleUnion *this) { diff --git a/clang/test/BSC/Positive/OwnedStruct/This/use_This_as_BSCMethod_parameter/expected.txt b/clang/test/BSC/Positive/OwnedStruct/This/use_This_as_BSCMethod_parameter/expected.txt index 705df83381e3cea958ee0df4bfa4947c9bfcfab0..08c96bc841003a2f9902b78731c59e50138027b6 100644 --- a/clang/test/BSC/Positive/OwnedStruct/This/use_This_as_BSCMethod_parameter/expected.txt +++ b/clang/test/BSC/Positive/OwnedStruct/This/use_This_as_BSCMethod_parameter/expected.txt @@ -1,4 +1,7 @@ 9 +9 +14 14 19 +19 diff --git a/clang/test/BSC/Positive/OwnedStruct/This/use_This_as_BSCMethod_parameter/use_This_as_BSCMethod_parameter.cbs b/clang/test/BSC/Positive/OwnedStruct/This/use_This_as_BSCMethod_parameter/use_This_as_BSCMethod_parameter.cbs index 9aaf23bc9f6042d849fb4037475fea44cf936567..8ab50d8ba65645b20fa6f6ed977a6c293361d78e 100644 --- a/clang/test/BSC/Positive/OwnedStruct/This/use_This_as_BSCMethod_parameter/use_This_as_BSCMethod_parameter.cbs +++ b/clang/test/BSC/Positive/OwnedStruct/This/use_This_as_BSCMethod_parameter/use_This_as_BSCMethod_parameter.cbs @@ -18,6 +18,10 @@ void S::dump(This* this) { printf("%d\n", this->a); } +void S::dump2(This this) { + printf("%d\n", this.a); +} + void int::f(This* this, int b) { *this = *this + b; } @@ -25,6 +29,10 @@ void int::dump(This* this) { printf("%d\n", *this); } +void int::dump2(This this) { + printf("%d\n", this); +} + owned struct G { public: T d; @@ -37,18 +45,24 @@ void G::dump(This* this) { printf("%d\n", this->d); } +void G::dump2(This this) { + printf("%d\n", this.d); +} int main() { S s = {.a = 5}; s.f(4); s.dump(); // print 9 + s.dump2(); // print 9 int c = 10; c.f(4); c.dump(); // print 14 + c.dump2(); // print 14 G g = {.d = 15}; g.f(4); g.dump(); // print 19 + g.dump2(); /// print 19 return 0; } diff --git a/clang/test/BSC/Positive/Ownership/member_func/member_func.cbs b/clang/test/BSC/Positive/Ownership/member_func/member_func.cbs index 6bb5ce7769bd37da28abef1712dd026da06d6460..5cf646531d98d8915fef5f8d37878f7ba3130695 100644 --- a/clang/test/BSC/Positive/Ownership/member_func/member_func.cbs +++ b/clang/test/BSC/Positive/Ownership/member_func/member_func.cbs @@ -41,28 +41,22 @@ int main() { struct S s1; s1.foo1(); s1.foo2(); - s1.foo3(); struct S s2; s2.foo4(); s2.foo5(); - s2.foo6(); struct G g1; g1.foo1(); g1.foo2(); - g1.foo3(); struct G g2; g2.foo4(); g2.foo5(); - g2.foo6(); int a1 = 5; a1.foo1(); a1.foo2(); - a1.foo3(); int a2 = 5; a2.foo4(); a2.foo5(); - a2.foo6(); return 0; } \ No newline at end of file