From 962cdd40083e7ae16a58a18b38fe12606fa4d306 Mon Sep 17 00:00:00 2001 From: zhaoxuhui Date: Sat, 25 Feb 2023 18:08:34 +0800 Subject: [PATCH] [BSC] check function is called by period or arrow --- .../clang/Basic/DiagnosticSemaKinds.td | 4 ++++ clang/lib/Parse/ParseDecl.cpp | 6 ++++-- clang/lib/Sema/SemaExprMember.cpp | 15 +++++++++++++++ .../Method/BuiltInType/int_function_call.cbs | 12 ++++++++++++ .../int_instance_function_many_arguments.cbs | 11 +++++++++++ .../BSC/Method/Enum/enum_function_call.cbs | 18 ++++++++++++++++++ .../enum_instance_function_many_arguments.cbs | 16 ++++++++++++++++ .../Method/Struct/struct_function_call.cbs | 16 ++++++++++++++++ ...truct_instance_function_many_arguments.cbs | 14 ++++++++++++++ .../BSC/Method/Union/union_function_call.cbs | 19 +++++++++++++++++++ ...union_instance_fucntion_many_arguments.cbs | 17 +++++++++++++++++ 11 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 clang/test/BSC/Method/BuiltInType/int_function_call.cbs create mode 100644 clang/test/BSC/Method/BuiltInType/int_instance_function_many_arguments.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_function_call.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_instance_function_many_arguments.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_function_call.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_instance_function_many_arguments.cbs create mode 100644 clang/test/BSC/Method/Union/union_function_call.cbs create mode 100644 clang/test/BSC/Method/Union/union_instance_fucntion_many_arguments.cbs diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b24dac80502f..80600c146673 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6454,6 +6454,10 @@ def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">; def err_no_member : Error<"no member named %0 in %1">; def err_no_member_overloaded_arrow : Error< "no member named %0 in %1; did you mean to use '->' instead of '.'?">; +def err_no_member_on_period : Error< + "no instance member named %0 in %1; did you mean to use '::' instead of '.'?">; +def err_no_member_on_arrow : Error< + "no instance member named %0 in %1; did you mean to use '::' instead of '->'?">; def err_member_not_yet_instantiated : Error< "no member %0 in %1; it has not yet been instantiated">; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index ac03c25ee8dd..e859be5f72fd 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2048,8 +2048,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false); D.complete(FirstDecl); if (FirstDecl) { - if (auto FD = dyn_cast(FirstDecl)) + if (auto FD = dyn_cast(FirstDecl)) { FD->setHasThisParam(D.HasThisParam); + FD->setExtendedType(D.getExtendedType()); + } DeclsInGroup.push_back(FirstDecl); } @@ -6550,7 +6552,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, if (ParamInfo.size() > 0) { ParmVarDecl *PD = dyn_cast_or_null(ParamInfo.data()[0].Param); - if (PD && D.getBSCScopeSpec()) + if (PD && !D.getExtendedType().isNull()) D.HasThisParam = PD->IsThisParam; } HasProto = ParamInfo.size() || getLangOpts().CPlusPlus diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index c994594ef2bd..30a7a2258383 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1233,6 +1233,21 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, QualType type; valueKind = VK_LValue; type = MemberFn->getType(); + if (!MemberFn->getExtendedType().isNull()) { + DeclContext *DC = + getASTContext().BSCDeclContextMap + [MemberFn->getExtendedType().getCanonicalType().getTypePtr()]; + // If this first parameter is not "this", + // it can only be called through '::'. + if (!MemberFn->getHasThisParam()) { + if (IsArrow) + Diag(OpLoc, diag::err_no_member_on_arrow) + << MemberName << DC << FixItHint::CreateReplacement(OpLoc, "::"); + else + Diag(OpLoc, diag::err_no_member_on_period) + << MemberName << DC << FixItHint::CreateReplacement(OpLoc, "::"); + } + } return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, MemberFn, FoundDecl, /*HadMultipleCandidates=*/false, diff --git a/clang/test/BSC/Method/BuiltInType/int_function_call.cbs b/clang/test/BSC/Method/BuiltInType/int_function_call.cbs new file mode 100644 index 000000000000..d06846e9da52 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_function_call.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -verify %s + +void int::increase() { +} + +int main() { + int x = 1; + int *y = &x; + x.increase(); // expected-error {{no instance member named 'increase' in 'struct __int'; did you mean to use '::' instead of '.'?}} + y->increase(); // expected-error {{no instance member named 'increase' in 'struct __int'; did you mean to use '::' instead of '->'?}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_many_arguments.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_many_arguments.cbs new file mode 100644 index 000000000000..f57769cdb582 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_many_arguments.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +void int::increase(int* this) { // expected-note {{'increase' declared here}} + *this = *this +1; +} + +int main() { + int x = 1; + x.increase(&x); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_function_call.cbs b/clang/test/BSC/Method/Enum/enum_function_call.cbs new file mode 100644 index 000000000000..f8cdb1f0366c --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_function_call.cbs @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int enum E::getA() { + return X4; +} + +int main() { + enum E foo = X3; + enum E *f = &foo; + foo.getA(); // expected-error {{no instance member named 'getA' in 'enum E'; did you mean to use '::' instead of '.'?}} + f->getA(); // expected-error {{no instance member named 'getA' in 'enum E'; did you mean to use '::' instead of '->'?}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_many_arguments.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_many_arguments.cbs new file mode 100644 index 000000000000..fc497d300863 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_instance_function_many_arguments.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int enum E::getA(enum E* this) { // expected-note {{'getA' declared here}} + return X4; +} + +int main() { + enum E foo = X3; + foo.getA(&foo); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_function_call.cbs b/clang/test/BSC/Method/Struct/struct_function_call.cbs new file mode 100644 index 000000000000..7ae8e560c758 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_function_call.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; +int struct Foo::getA() { + return 1; +} + +int main() { + struct Foo foo; + struct Foo *f = &foo; + foo.getA(); // expected-error {{no instance member named 'getA' in 'struct Foo'; did you mean to use '::' instead of '.'?}} + f->getA(); // expected-error {{no instance member named 'getA' in 'struct Foo'; did you mean to use '::' instead of '->'?}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_many_arguments.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_many_arguments.cbs new file mode 100644 index 000000000000..ade797cabd11 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_many_arguments.cbs @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; +int struct Foo::getA(struct Foo* this) { // expected-note {{'getA' declared here}} + return this->a; +} + +int main() { + struct Foo foo; + foo.getA(&foo); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_function_call.cbs b/clang/test/BSC/Method/Union/union_function_call.cbs new file mode 100644 index 000000000000..4ef37fe8dd1e --- /dev/null +++ b/clang/test/BSC/Method/Union/union_function_call.cbs @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA() { + return 1; +} + +int main() { + union SimpleUnion foo = {.ui = 1}; + union SimpleUnion *f = &foo; + foo.getA(); // expected-error {{no instance member named 'getA' in 'union SimpleUnion'; did you mean to use '::' instead of '.'?}} + f->getA(); // expected-error {{no instance member named 'getA' in 'union SimpleUnion'; did you mean to use '::' instead of '->'?}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_instance_fucntion_many_arguments.cbs b/clang/test/BSC/Method/Union/union_instance_fucntion_many_arguments.cbs new file mode 100644 index 000000000000..f08e3ceb9fe5 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_instance_fucntion_many_arguments.cbs @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(union SimpleUnion * this) { // expected-note {{'getA' declared here}} + return this->ui; +} + +int main() { + union SimpleUnion u = {.ui = 1}; + u.getA(&u); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file -- Gitee