From b17fa8cb0e44720abaa8c10f41e6eb90eded77b0 Mon Sep 17 00:00:00 2001 From: zhaoxuhui Date: Wed, 21 Jun 2023 15:53:49 +0800 Subject: [PATCH] [BSC] bugfix generic nested calls --- clang/include/clang/Sema/Sema.h | 21 +++++------ clang/lib/AST/Expr.cpp | 2 +- clang/lib/Parse/ParseExpr.cpp | 10 +++++ clang/lib/Parse/ParseExprCXX.cpp | 37 +++++++++++++++++++ clang/lib/Sema/SemaCXXScopeSpec.cpp | 21 ++++++----- clang/lib/Sema/SemaExpr.cpp | 12 +++--- clang/lib/Sema/SemaInit.cpp | 3 +- clang/lib/Sema/SemaTemplate.cpp | 13 +++++-- clang/lib/Sema/TreeTransform.h | 7 ++-- .../generic_func_nested_call.cbs | 33 +++++++++++++++++ .../generic_func_nested_call_error.cbs | 20 ++++++++++ 11 files changed, 143 insertions(+), 36 deletions(-) create mode 100644 clang/test/BSC/Generic/GenericTypeMethods/generic_func_nested_call.cbs create mode 100644 clang/test/BSC/Generic/GenericTypeMethods/generic_func_nested_call_error.cbs diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e0fe9df6e842..e00dd6f6b042 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5453,7 +5453,8 @@ public: SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool isAddressOfOperand, - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + QualType ExtendedTy = QualType()); /// If \p D cannot be odr-used in the current expression evaluation context, /// return a reason explaining why. Otherwise, return NOUR_None. @@ -5509,7 +5510,8 @@ public: ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + QualType ExtendedTy = QualType()); ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, @@ -6896,16 +6898,11 @@ public: /// /// /// \returns true if an error occurred, false otherwise. - bool ActOnCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - TemplateTy TemplateName, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc, - SourceLocation CCLoc, - bool EnteringContext); + bool ActOnCXXNestedNameSpecifier( + Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + TemplateTy &TemplateName, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc, SourceLocation CCLoc, bool EnteringContext); /// Given a C++ nested-name-specifier, produce an annotation value /// that the parser can use later to reconstruct the given diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index ca477e6500c5..5b9b844dd072 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -102,7 +102,7 @@ const Expr *Expr::skipRValueSubobjectAdjustments( } } else if (const MemberExpr *ME = dyn_cast(E)) { if (!ME->isArrow()) { - assert(ME->getBase()->getType()->isRecordType()); + assert(ME->getBase()->getType()->isRecordType() || ME->getBase()->getType()->isEnumeralType()); if (FieldDecl *Field = dyn_cast(ME->getMemberDecl())) { if (!Field->isBitField() && !Field->getType()->isReferenceType()) { E = ME->getBase(); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 0b06ff82db4f..29a9cfa7d1be 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -742,6 +742,16 @@ ExprResult Parser::ParseOptionalBSCScopeSpecifier( BSS.setBeginLoc(DS.getBeginLoc()); QualType T = Actions.ConvertBSCScopeSpecToType(D, DS.getBeginLoc(), false, BSS, DS); + // For generic member functions, if the generic 'T' comes from a scope when + // called, we need to obtain the NestedNameSpecifier from the scope and store + // it in QualType to facilitate the creation of 'DependentScopeDeclRefExpr' + // ast nodes. + auto *TST = dyn_cast_or_null(T.getCanonicalType().getTypePtr()); + if (Tok.is(tok::coloncolon) && TST) { + TagDecl *TD = dyn_cast_or_null(Actions.getASTContext().BSCDeclContextMap[TST]); + if (TD) + TD->setQualifierInfo(DS.getTypeSpecScope().getWithLocInContext(Actions.getASTContext())); + } HasBSCScopeSpec = TryConsumeToken(tok::coloncolon); D.getBSCScopeSpec() = BSS; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index ebd68ec5ba3e..f9f3ea5c63f7 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -728,6 +728,43 @@ bool Parser::ParseOptionalBSCGenericSpecifier( continue; } + if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) { + TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); + if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde)) { + *MayBePseudoDestructor = true; + return false; + } + + if (LastII) + *LastII = TemplateId->Name; + + SourceLocation CCLoc = NextToken().getLocation(); + + HasScopeSpecifier = true; + + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + ParsedTemplateTy OldTemplate = TemplateId->Template; + if (TemplateId->isInvalid() || + Actions.ActOnCXXNestedNameSpecifier(getCurScope(), + SS, + TemplateId->TemplateKWLoc, + TemplateId->Template, + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->RAngleLoc, + CCLoc, + EnteringContext)) { + SourceLocation StartLoc + = SS.getBeginLoc().isValid()? SS.getBeginLoc() + : TemplateId->TemplateNameLoc; + SS.SetInvalid(SourceRange(StartLoc, CCLoc)); + } + if (TemplateId->Template.get().getAsTemplateDecl()) + TemplateId->Kind = TNK_Type_template; + } + // The rest of the nested-name-specifier possibilities start with // tok::identifier. if (Tok.isNot(tok::identifier)) diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index a357f4e4df73..0f4cef6221c9 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -910,16 +910,11 @@ bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, /*ScopeLookupResult=*/nullptr, true); } -bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - TemplateTy OpaqueTemplate, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation RAngleLoc, - SourceLocation CCLoc, - bool EnteringContext) { +bool Sema::ActOnCXXNestedNameSpecifier( + Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + TemplateTy &OpaqueTemplate, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc, SourceLocation CCLoc, bool EnteringContext) { if (SS.isInvalid()) return true; @@ -963,6 +958,12 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, resolveAssumedTemplateNameAsType(S, Template, TemplateNameLoc)) return true; + // For the case of "struct MyStruct11: foo()", if the name of + // the struct is incorrect, correct it in a timely manner to + // prevent duplicate errors from being reported. + if (getLangOpts().BSC) + OpaqueTemplate = TemplateTy::make(Template); + TemplateDecl *TD = Template.getAsTemplateDecl(); if (Template.getAsOverloadedTemplate() || DTN || isa(TD) || isa(TD)) { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 3b8d14f2969a..651d7167b86b 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2559,11 +2559,14 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, } else { DependentID = true; } + } else if (!T.isNull()) { + if (dyn_cast_or_null(T.getCanonicalType().getTypePtr())) + DependentID = true; } if (DependentID) return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, - IsAddressOfOperand, TemplateArgs); + IsAddressOfOperand, TemplateArgs, T); // Perform the required lookup. LookupResult R(*this, NameInfo, (Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam) @@ -7145,10 +7148,9 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_PRValue, RParenLoc, CurFPFeatureOverrides(), NumParams, UsesADL); - if (Fn->IsDesugaredBSCMethodCall) { - // Set desugar flag true in transformation. - TheCall->getCallee()->IsDesugaredBSCMethodCall = true; - } + // Keep flag unchanged in transformation. + TheCall->getCallee()->IsDesugaredBSCMethodCall = Fn->IsDesugaredBSCMethodCall; + TheCall->getCallee()->HasBSCScopeSpec = Fn->HasBSCScopeSpec; } if (!Context.isDependenceAllowed()) { diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index fb04a431c2af..85c8e3e683f8 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -499,7 +499,8 @@ ExprResult InitListChecker::PerformEmptyInit(SourceLocation Loc, // If there are fewer initializer-clauses in the list than there are // members in the aggregate, then each member not explicitly initialized // ... - bool EmptyInitList = SemaRef.getLangOpts().CPlusPlus11 && + bool EmptyInitList = + (SemaRef.getLangOpts().CPlusPlus11 || SemaRef.getLangOpts().BSC) && Entity.getType()->getBaseElementTypeUnsafe()->isRecordType(); if (EmptyInitList) { // C++1y / DR1070: diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 43846d9626e7..41f2cfa3dff7 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -729,7 +729,8 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool isAddressOfOperand, - const TemplateArgumentListInfo *TemplateArgs) { + const TemplateArgumentListInfo *TemplateArgs, + QualType ExtendedTy) { DeclContext *DC = getFunctionLevelDeclContext(); // C++11 [expr.prim.general]p12: @@ -765,16 +766,22 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, FirstQualifierInScope, NameInfo, TemplateArgs); } - return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); + return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs, ExtendedTy); } ExprResult Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs) { + const TemplateArgumentListInfo *TemplateArgs, + QualType ExtendedTy) { // DependentScopeDeclRefExpr::Create requires a valid QualifierLoc NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); + if (!ExtendedTy.isNull()) { + TagDecl *TD = dyn_cast_or_null(getASTContext().BSCDeclContextMap[ExtendedTy.getCanonicalType().getTypePtr()]); + assert(TD && "no corresponding DeclContext found for this type"); + QualifierLoc = TD->getQualifierLoc(); + } if (!QualifierLoc) return ExprError(); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 16cb81223009..23aebf064cc7 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -11051,10 +11051,9 @@ TreeTransform::TransformCallExpr(CallExpr *E) { if (Callee.isInvalid()) return ExprError(); - if (E->getCallee()->IsDesugaredBSCMethodCall) { - // Keep desugar flag true in transformation. - Callee.get()->IsDesugaredBSCMethodCall = true; - } + // Keep flag unchanged in transformation. + Callee.get()->IsDesugaredBSCMethodCall = E->getCallee()->IsDesugaredBSCMethodCall; + Callee.get()->HasBSCScopeSpec = E->getCallee()->HasBSCScopeSpec; // Transform arguments. bool ArgChanged = false; diff --git a/clang/test/BSC/Generic/GenericTypeMethods/generic_func_nested_call.cbs b/clang/test/BSC/Generic/GenericTypeMethods/generic_func_nested_call.cbs new file mode 100644 index 000000000000..97635529d592 --- /dev/null +++ b/clang/test/BSC/Generic/GenericTypeMethods/generic_func_nested_call.cbs @@ -0,0 +1,33 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// expected-no-diagnostics + +struct S { + T res; +}; + +struct MyStruct { + T res; + struct S s; +}; + +T struct MyStruct::foo(struct MyStruct *this, T a) { + this->res = a; + return this->res; +} + +T f1(T a) { + struct MyStruct s = {.res = a}; + return struct MyStruct::foo(&s, a); +} + +T f2(T a) { + struct MyStruct s = {.res = a}; + return s.foo(a); +} + +int main() { + int res1 = f1(2); + int res2 = f2(2); + return res1 - res2; +} \ No newline at end of file diff --git a/clang/test/BSC/Generic/GenericTypeMethods/generic_func_nested_call_error.cbs b/clang/test/BSC/Generic/GenericTypeMethods/generic_func_nested_call_error.cbs new file mode 100644 index 000000000000..1676ac54d15f --- /dev/null +++ b/clang/test/BSC/Generic/GenericTypeMethods/generic_func_nested_call_error.cbs @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify %s + +struct MyStruct { // expected-note {{'MyStruct' declared here}} + T res; +}; + +T struct MyStruct::foo(struct MyStruct *this, T a) { + this->res = a; + return this->res; +} + +T f1(T a) { + struct MyStruct s = {.res = a}; + return struct MyStruct11::foo(&s, a); // expected-error {{no template named 'MyStruct11'; did you mean 'MyStruct'?}} +} + +int main() { + int res1 = f1(2); + return res1; +} \ No newline at end of file -- Gitee