From 7106a7d4f4ad70a0f61ab63769cc64182b23421e Mon Sep 17 00:00:00 2001 From: l00846161 Date: Sat, 9 Sep 2023 18:10:17 +0800 Subject: [PATCH] [BSCmethod] use This* as BSCmethod parameter type for example, you can define a BSCmethod below void struct S::foo(This* this){} --- clang/include/clang/Parse/Parser.h | 4 +- clang/include/clang/Sema/DeclSpec.h | 4 +- clang/include/clang/Sema/Sema.h | 3 +- clang/lib/Parse/ParseDecl.cpp | 19 ++++--- clang/lib/Sema/SemaDecl.cpp | 32 ++++++++++- clang/lib/Sema/SemaTemplate.cpp | 14 +++-- .../This/use_This_as_BSCMethod_parameter.cbs | 57 +++++++++++++++++++ 7 files changed, 116 insertions(+), 17 deletions(-) create mode 100644 clang/test/BSC/Positive/Method/This/use_This_as_BSCMethod_parameter.cbs diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index b0ca13127dcd..89811d2dc380 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3055,8 +3055,8 @@ private: void ParseParameterDeclarationClause( DeclaratorContext DeclaratorContext, ParsedAttributes &attrs, SmallVectorImpl &ParamInfo, - SourceLocation &EllipsisLoc, const Type *typePtr = nullptr, - bool isTraitMem = false); + SourceLocation &EllipsisLoc, QualType ExtendedType = QualType(), + bool isTraitMem = false, bool isBSCGenericType = false); void ParseBracketDeclarator(Declarator &D); void ParseMisplacedBracketDeclarator(Declarator &D); diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 3ac0c6918cf6..d52da9cb47dc 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -236,7 +236,9 @@ private: public: /// Used to mark parameters that include 'this'. bool HasThisParam = false; - + /// Used to mark ExtendedType is a Generic type + bool isGenericType = false; + QualType getExtendedType() const { return ExtendedType; } void setExtendedType(QualType ExtendedType) { this->ExtendedType = ExtendedType; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b779c16fc4dd..0db794c58b60 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2911,7 +2911,8 @@ public: void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D); // FIXME: Not good enough to add two extra args. Decl *ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize = 0, - const Type *TypePtr = nullptr); + QualType ExtendedType = QualType(), + bool isBSCGenericType = false); ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 97cb5d0516bd..1d46d011bcb6 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6396,12 +6396,15 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // BSC if (getLangOpts().BSC && FindUntil(tok::coloncolon) && !IsParsingBSCGenericParameters) { + bool isGenericType = false; + if (FindUntil(tok::less)) isGenericType = true; DeclSpec DS(AttrFactory); ParseBSCScopeSpecifiers(DS); TryConsumeToken(tok::coloncolon); BSCScopeSpec BSS; BSS.setBeginLoc(DS.getBeginLoc()); + if (isGenericType) BSS.isGenericType = true; Actions.ConvertBSCScopeSpecToType(D, DS.getBeginLoc(), true, BSS, DS); D.getBSCScopeSpec() = BSS; (this->*DirectDeclParser)(D); @@ -7267,15 +7270,15 @@ void Parser::ParseFunctionDeclarator(Declarator &D, ProhibitAttributes(FnAttrs); } else { if (Tok.isNot(tok::r_paren)) { - const Type *TypePtr = nullptr; + bool isBSCGenericType; + QualType ExtendedType; if (D.getBSCScopeSpec().isNotEmpty() && !D.getBSCScopeSpec().getExtendedType().isNull()) { - TypePtr = D.getBSCScopeSpec().getExtendedType().getTypePtrOrNull(); - if (TypePtr) - TypePtr = TypePtr->getCanonicalTypeUnqualified().getTypePtrOrNull(); + isBSCGenericType = D.getBSCScopeSpec().isGenericType; + ExtendedType = D.getBSCScopeSpec().getExtendedType(); } ParseParameterDeclarationClause(D.getContext(), FirstArgAttrs, ParamInfo, - EllipsisLoc, TypePtr, isTraitMem); + EllipsisLoc, ExtendedType, isTraitMem, isBSCGenericType); } else if (isTraitMem) Diag(Tok.getLocation(), diag::invalid_param_for_trait_member); else if (RequiresArg) @@ -7546,7 +7549,8 @@ void Parser::ParseFunctionDeclaratorIdentifierList( void Parser::ParseParameterDeclarationClause( DeclaratorContext DeclaratorCtx, ParsedAttributes &FirstArgAttrs, SmallVectorImpl &ParamInfo, - SourceLocation &EllipsisLoc, const Type *typePtr, bool isTraitMem) { + SourceLocation &EllipsisLoc, QualType ExtendedType, + bool isTraitMem, bool isBSCGenericType) { // Avoid exceeding the maximum function scope depth. // See https://bugs.llvm.org/show_bug.cgi?id=19607 @@ -7672,7 +7676,8 @@ void Parser::ParseParameterDeclarationClause( // Inform the actions module about the parameter declarator, so it gets // added to the current scope. Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator, - ParamInfo.size(), typePtr); + ParamInfo.size(), ExtendedType, + isBSCGenericType); // Parse the default argument, if any. We parse the default // arguments in all dialects; the semantic analysis in // ActOnParamDefaultArgument will reject the default argument in diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 8758f3f9f723..a0d99315ecce 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -14337,7 +14337,7 @@ void Sema::CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D) { /// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() /// to introduce parameters into function prototype scope. Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize, - const Type *TypePtr) { + QualType ExtendedType, bool isBSCGenericType) { const DeclSpec &DS = D.getDeclSpec(); // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. @@ -14383,6 +14383,9 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize, // Check for redeclaration of parameters, e.g. int foo(int x, int x); IdentifierInfo *II = D.getIdentifier(); 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") { if (ParamSize == 0) { @@ -14393,7 +14396,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize, ThisTypePtr = ThisTypePtr->getCanonicalTypeUnqualified().getTypePtrOrNull(); } - if (TypePtr != ThisTypePtr) { + if (DS.getTypeSpecType() != clang::TST_This && TypePtr != ThisTypePtr) { Diag(D.getBeginLoc(), diag::err_type_unsupported) << parmDeclType.getAsString(); } @@ -14433,6 +14436,31 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize, // Temporarily put parameter variables in the translation unit, not // the enclosing context. This prevents them from accidentally // looking like class members in C++. + + // Use This* as BSCMethod parameter, + // For example void struct S::f(This* this); + if (getLangOpts().BSC && TypePtr && DS.getTypeSpecType() == clang::TST_This) { + parmDeclType = Context.getPointerType(ExtendedType); + TInfo = Context.CreateTypeSourceInfo(parmDeclType); + + // if EntendedType is a generic type, + // TemplateArgumentLocInfo is needed when instantiation, + if (isBSCGenericType) { + UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc(); + CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); + CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); + TemplateSpecializationTypeLoc SpecTL = + CurrTL.getAs(); + const TemplateSpecializationType* SpecType = SpecTL.getTypePtr(); + for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i) { + QualType TemplateArg = SpecType->getArg(i).getAsType(); + TypeSourceInfo *TemplateArgTypeInfo = + Context.getTrivialTypeSourceInfo(TemplateArg, DS.getBeginLoc()); + SpecTL.setArgLocInfo(i, TemplateArgumentLocInfo(TemplateArgTypeInfo)); + } + } + } + ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(), D.getBeginLoc(), D.getIdentifierLoc(), II, parmDeclType, TInfo, SC); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 7c0162464a07..dfd5ae680b30 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4186,10 +4186,16 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, // Construct an elaborated type containing the nested-name-specifier (if any) // and tag keyword. - Result = Context.getElaboratedType(Keyword, SS.getScopeRep(), Result); - ElaboratedTypeLoc ElabTL = TLB.push(Result); - ElabTL.setElaboratedKeywordLoc(TagLoc); - ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); + if (Context.getLangOpts().BSC) { + Result = Context.getElaboratedType(Keyword, nullptr, Result); + ElaboratedTypeLoc ElabTL = TLB.push(Result); + ElabTL.setElaboratedKeywordLoc(TagLoc); + } else { + Result = Context.getElaboratedType(Keyword, SS.getScopeRep(), Result); + ElaboratedTypeLoc ElabTL = TLB.push(Result); + ElabTL.setElaboratedKeywordLoc(TagLoc); + ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); + } return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); } diff --git a/clang/test/BSC/Positive/Method/This/use_This_as_BSCMethod_parameter.cbs b/clang/test/BSC/Positive/Method/This/use_This_as_BSCMethod_parameter.cbs new file mode 100644 index 000000000000..d7366197a4b8 --- /dev/null +++ b/clang/test/BSC/Positive/Method/This/use_This_as_BSCMethod_parameter.cbs @@ -0,0 +1,57 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// expected-no-diagnostics + +#include +trait M{ + void f(This* this, int b); + void dump(This* this); +}; + +typedef struct S { + int a; +}S1; +void S1::f(This* this, int b) { + this->a = this->a + b; +} +void struct S::dump(This* this) { + printf("%d\n", this->a); +} + +void int::f(This* this, int b) { + *this = *this + b; +} +void int::dump(This* this) { + printf("%d\n", *this); +} + +struct G { + T d; +}; +void struct G::f(This* this, int b) { + this->d = this->d + b; +} +void struct G::dump(This* this) { + printf("%d\n", this->d); +} + +impl trait M for int; +impl trait M for S1; + +void foo(trait M* t) { + t->f(4); + t->dump(); +} + +int main() { + struct S s = {.a = 5}; + foo(&s); // print 9 + int c = 10; + foo(&c); // print 14 + + struct G g = {.d = 8}; + g.f(4); + g.dump(); // print 12 + + return 0; +} -- Gitee