From 7797331bb5110854136bd067dc8d2233c820a055 Mon Sep 17 00:00:00 2001 From: zhaoxuhui Date: Tue, 7 Mar 2023 19:02:22 +0800 Subject: [PATCH 1/4] [BSC] fix error message for function undeclared --- clang/include/clang/Sema/Sema.h | 24 +++++---- clang/include/clang/Sema/SemaInternal.h | 15 +++--- clang/include/clang/Sema/TypoCorrection.h | 29 +++++++---- clang/lib/Parse/ParseExpr.cpp | 2 + clang/lib/Sema/SemaExpr.cpp | 33 +++++++++++-- clang/lib/Sema/SemaLookup.cpp | 49 +++++++++---------- .../int_function_pointer_undeclared.cbs | 7 +-- .../Enum/enum_function_pointer_undeclared.cbs | 7 +-- .../Struct/struct_function_undeclared.cbs | 7 +-- .../struct_static_function_not_found.cbs | 15 ++++++ .../union_function_pointer_undeclared.cbs | 7 +-- 11 files changed, 123 insertions(+), 72 deletions(-) create mode 100644 clang/test/BSC/Method/Struct/struct_static_function_not_found.cbs diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b0c085d98044..fd5ed2f95055 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4041,11 +4041,10 @@ private: std::unique_ptr makeTypoCorrectionConsumer(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, - CXXScopeSpec *SS, - CorrectionCandidateCallback &CCC, + CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT, - bool ErrorRecovery); + bool ErrorRecovery, QualType ET = QualType()); public: const TypoExprState &getTypoExprState(TypoExpr *TE) const; @@ -4147,15 +4146,13 @@ public: const ObjCObjectPointerType *OPT = nullptr, bool RecordFailure = true); - TypoExpr *CorrectTypoDelayed(const DeclarationNameInfo &Typo, - Sema::LookupNameKind LookupKind, Scope *S, - CXXScopeSpec *SS, - CorrectionCandidateCallback &CCC, - TypoDiagnosticGenerator TDG, - TypoRecoveryCallback TRC, CorrectTypoKind Mode, - DeclContext *MemberContext = nullptr, - bool EnteringContext = false, - const ObjCObjectPointerType *OPT = nullptr); + TypoExpr *CorrectTypoDelayed( + const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, + Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, + TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, + CorrectTypoKind Mode, DeclContext *MemberContext = nullptr, + bool EnteringContext = false, const ObjCObjectPointerType *OPT = nullptr, + QualType ET = QualType()); /// Process any TypoExprs in the given Expr and its children, /// generating diagnostics as appropriate and returning a new Expr if there @@ -5087,7 +5084,8 @@ public: DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, - ArrayRef Args = None, TypoExpr **Out = nullptr); + ArrayRef Args = None, TypoExpr **Out = nullptr, + QualType ET = QualType()); DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S, IdentifierInfo *II); diff --git a/clang/include/clang/Sema/SemaInternal.h b/clang/include/clang/Sema/SemaInternal.h index 842eec099540..d2175b0b4532 100644 --- a/clang/include/clang/Sema/SemaInternal.h +++ b/clang/include/clang/Sema/SemaInternal.h @@ -88,20 +88,20 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer { typedef std::map TypoEditDistanceMap; public: - TypoCorrectionConsumer(Sema &SemaRef, - const DeclarationNameInfo &TypoName, - Sema::LookupNameKind LookupKind, - Scope *S, CXXScopeSpec *SS, + TypoCorrectionConsumer(Sema &SemaRef, const DeclarationNameInfo &TypoName, + Sema::LookupNameKind LookupKind, Scope *S, + CXXScopeSpec *SS, std::unique_ptr CCC, - DeclContext *MemberContext, - bool EnteringContext) + DeclContext *MemberContext, bool EnteringContext, + QualType ET = QualType()) : Typo(TypoName.getName().getAsIdentifierInfo()), CurrentTCIndex(0), SavedTCIndex(0), SemaRef(SemaRef), S(S), SS(SS ? std::make_unique(*SS) : nullptr), CorrectionValidator(std::move(CCC)), MemberContext(MemberContext), Result(SemaRef, TypoName, LookupKind), Namespaces(SemaRef.Context, SemaRef.CurContext, SS), - EnteringContext(EnteringContext), SearchNamespaces(false) { + EnteringContext(EnteringContext), SearchNamespaces(false), + ExtendedType(ET) { Result.suppressDiagnostics(); // Arrange for ValidatedCorrections[0] to always be an empty correction. ValidatedCorrections.push_back(TypoCorrection()); @@ -308,6 +308,7 @@ private: Sema &SemaRef; Scope *S; + QualType ExtendedType; std::unique_ptr SS; std::unique_ptr CorrectionValidator; DeclContext *MemberContext; diff --git a/clang/include/clang/Sema/TypoCorrection.h b/clang/include/clang/Sema/TypoCorrection.h index e0f8d152dbe5..c56ad1f5d115 100644 --- a/clang/include/clang/Sema/TypoCorrection.h +++ b/clang/include/clang/Sema/TypoCorrection.h @@ -58,25 +58,26 @@ public: TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl, NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0, - unsigned QualifierDistance = 0) + unsigned QualifierDistance = 0, Type *ET = nullptr) : CorrectionName(Name), CorrectionNameSpec(NNS), - CharDistance(CharDistance), QualifierDistance(QualifierDistance) { + CharDistance(CharDistance), QualifierDistance(QualifierDistance), + ExtendedType(ET) { if (NameDecl) CorrectionDecls.push_back(NameDecl); } TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = nullptr, - unsigned CharDistance = 0) + unsigned CharDistance = 0, Type *ET = nullptr) : CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS), - CharDistance(CharDistance) { + CharDistance(CharDistance), ExtendedType(ET) { if (Name) CorrectionDecls.push_back(Name); } TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = nullptr, - unsigned CharDistance = 0) + unsigned CharDistance = 0, Type *ET = nullptr) : CorrectionName(Name), CorrectionNameSpec(NNS), - CharDistance(CharDistance) {} + CharDistance(CharDistance), ExtendedType(ET) {} TypoCorrection() = default; @@ -97,6 +98,11 @@ public: ForceSpecifierReplacement = (NNS != nullptr); } + /// Gets the QualType needed to use the typo correction for BSC + Type *getExtendedType() const { return ExtendedType; } + + void setExtendedType(Type *ET) { ExtendedType = ET; } + void WillReplaceSpecifier(bool ForceReplacement) { ForceSpecifierReplacement = ForceReplacement; } @@ -265,6 +271,7 @@ private: // Results. DeclarationName CorrectionName; NestedNameSpecifier *CorrectionNameSpec = nullptr; + Type *ExtendedType = nullptr; SmallVector CorrectionDecls; unsigned CharDistance = 0; unsigned QualifierDistance = 0; @@ -283,8 +290,9 @@ public: static const unsigned InvalidDistance = TypoCorrection::InvalidDistance; explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr, - NestedNameSpecifier *TypoNNS = nullptr) - : Typo(Typo), TypoNNS(TypoNNS) {} + NestedNameSpecifier *TypoNNS = nullptr, + const Type *ExtendedType = nullptr) + : Typo(Typo), TypoNNS(TypoNNS), ExtendedType(ExtendedType) {} virtual ~CorrectionCandidateCallback() = default; @@ -321,6 +329,7 @@ public: void setTypoName(IdentifierInfo *II) { Typo = II; } void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; } + void setExtendType(const Type *ET) { ExtendedType = ET; } // Flags for context-dependent keywords. WantFunctionLikeCasts is only // used/meaningful when WantCXXNamedCasts is false. @@ -342,11 +351,13 @@ protected: candidate.getCorrectionAsIdentifierInfo() == Typo && // FIXME: This probably does not return true when both // NestedNameSpecifiers have the same textual representation. - candidate.getCorrectionSpecifier() == TypoNNS; + candidate.getCorrectionSpecifier() == TypoNNS && + candidate.getExtendedType() == ExtendedType; } IdentifierInfo *Typo; NestedNameSpecifier *TypoNNS; + const Type *ExtendedType; }; class DefaultFilterCCC final : public CorrectionCandidateCallback { diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 6fb1a7dba79a..1d3b012c29e8 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1273,6 +1273,8 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, } else { Validator.WantRemainingKeywords = Tok.isNot(tok::r_paren); } + if (!T.isNull()) + Validator.setExtendType(T.getTypePtr()); Name.setIdentifier(&II, ILoc); Res = Actions.ActOnIdExpression( getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren), diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8843c1f8d082..6cbbfac46104 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2102,7 +2102,7 @@ Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id, } static void emitEmptyLookupTypoDiagnostic( - const TypoCorrection &TC, Sema &SemaRef, const CXXScopeSpec &SS, + const TypoCorrection &TC, Sema &SemaRef, const CXXScopeSpec &SS, QualType ET, DeclarationName Typo, SourceLocation TypoLoc, ArrayRef Args, unsigned DiagnosticID, unsigned DiagnosticSuggestID) { DeclContext *Ctx = @@ -2124,6 +2124,25 @@ static void emitEmptyLookupTypoDiagnostic( unsigned NoteID = TC.getCorrectionDeclAs() ? diag::note_implicit_param_decl : diag::note_previous_decl; + if (!ET.isNull() && SemaRef.getLangOpts().BSC) { + const Type *BasedType = ET.getCanonicalType().getTypePtr(); + if (const RecordType *RTy = dyn_cast( + BasedType)) { // struct type or union type + Ctx = RTy->getDecl(); + } else if (const EnumType *ETy = + dyn_cast(BasedType)) { // enum type + Ctx = ETy->getDecl(); + } else if (const BuiltinType *BTy = + dyn_cast(BasedType)) { // builtin type + SemaRef.diagnoseTypo( + TC, + SemaRef.PDiag(diag::err_no_member_suggest) + << Typo << BTy->getNameAsCString(SemaRef.getPrintingPolicy()) + << DroppedSpecifier << SS.getRange(), + SemaRef.PDiag(NoteID)); + return; + } + } if (!Ctx) SemaRef.diagnoseTypo(TC, SemaRef.PDiag(DiagnosticSuggestID) << Typo, SemaRef.PDiag(NoteID)); @@ -2207,7 +2226,8 @@ bool Sema::DiagnoseDependentMemberLookup(LookupResult &R) { bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs, - ArrayRef Args, TypoExpr **Out) { + ArrayRef Args, TypoExpr **Out, + QualType ET) { DeclarationName Name = R.getLookupName(); unsigned diagnostic = diag::err_undeclared_var_use; @@ -2224,6 +2244,9 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, // original lookup would not have found something because it was a // dependent name. DeclContext *DC = SS.isEmpty() ? CurContext : nullptr; + if (!ET.isNull()) { + DC = getASTContext().BSCDeclContextMap[ET.getCanonicalType().getTypePtr()]; + } while (DC) { if (isa(DC)) { LookupQualifiedName(R, DC); @@ -2263,10 +2286,10 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, *Out = CorrectTypoDelayed( R.getLookupNameInfo(), R.getLookupKind(), S, &SS, CCC, [=](const TypoCorrection &TC) { - emitEmptyLookupTypoDiagnostic(TC, *this, SS, Name, TypoLoc, Args, + emitEmptyLookupTypoDiagnostic(TC, *this, SS, ET, Name, TypoLoc, Args, diagnostic, diagnostic_suggest); }, - nullptr, CTK_ErrorRecovery); + nullptr, CTK_ErrorRecovery, nullptr, false, nullptr, ET); if (*Out) return true; } else if (S && @@ -2560,7 +2583,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // a template name, but we happen to have always already looked up the name // before we get here if it must be a template name. if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator, nullptr, - None, &TE)) { + None, &TE, T)) { if (TE && KeywordReplacement) { auto &State = getTypoExprState(TE); auto BestTC = State.Consumer->getNextCorrection(); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index f9b5e7dc2a6c..75d6b79aa3f3 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -2440,8 +2440,8 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, DeclContext *DC = getASTContext().BSCDeclContextMap[T.getCanonicalType().getTypePtr()]; if (DC) return LookupQualifiedName(R, DC); - else - Diag(R.getNameLoc(), diag::err_undeclared_var_use) << R.getLookupName(); + else + return false; } // Perform unqualified name lookup starting in the given scope. @@ -4095,14 +4095,13 @@ static bool isCandidateViable(CorrectionCandidateCallback &CCC, return Candidate.getEditDistance(false) != TypoCorrection::InvalidDistance; } -static void LookupPotentialTypoResult(Sema &SemaRef, - LookupResult &Res, - IdentifierInfo *Name, - Scope *S, CXXScopeSpec *SS, +static void LookupPotentialTypoResult(Sema &SemaRef, LookupResult &Res, + IdentifierInfo *Name, Scope *S, + CXXScopeSpec *SS, DeclContext *MemberContext, bool EnteringContext, - bool isObjCIvarLookup, - bool FindHidden); + bool isObjCIvarLookup, bool FindHidden, + QualType ET = QualType()); /// Check whether the declarations found for a typo correction are /// visible. Set the correction's RequiresImport flag to true if none of the @@ -4347,17 +4346,19 @@ bool TypoCorrectionConsumer::resolveCorrection(TypoCorrection &Candidate) { IdentifierInfo *Name = Candidate.getCorrectionAsIdentifierInfo(); DeclContext *TempMemberContext = MemberContext; CXXScopeSpec *TempSS = SS.get(); + QualType ET = ExtendedType; retry_lookup: - LookupPotentialTypoResult(SemaRef, Result, Name, S, TempSS, TempMemberContext, - EnteringContext, - CorrectionValidator->IsObjCIvarLookup, - Name == Typo && !Candidate.WillReplaceSpecifier()); + LookupPotentialTypoResult( + SemaRef, Result, Name, S, TempSS, TempMemberContext, EnteringContext, + CorrectionValidator->IsObjCIvarLookup, + Name == Typo && !Candidate.WillReplaceSpecifier(), ET); switch (Result.getResultKind()) { case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: case LookupResult::FoundUnresolvedValue: if (TempSS) { // Immediately retry the lookup without the given CXXScopeSpec + ET = QualType(); TempSS = nullptr; Candidate.WillReplaceSpecifier(true); goto retry_lookup; @@ -4590,14 +4591,10 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier( } /// Perform name lookup for a possible result for typo correction. -static void LookupPotentialTypoResult(Sema &SemaRef, - LookupResult &Res, - IdentifierInfo *Name, - Scope *S, CXXScopeSpec *SS, - DeclContext *MemberContext, - bool EnteringContext, - bool isObjCIvarLookup, - bool FindHidden) { +static void LookupPotentialTypoResult( + Sema &SemaRef, LookupResult &Res, IdentifierInfo *Name, Scope *S, + CXXScopeSpec *SS, DeclContext *MemberContext, bool EnteringContext, + bool isObjCIvarLookup, bool FindHidden, QualType ET) { Res.suppressDiagnostics(); Res.clear(); Res.setLookupName(Name); @@ -4625,7 +4622,7 @@ static void LookupPotentialTypoResult(Sema &SemaRef, } SemaRef.LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false, - EnteringContext); + EnteringContext, ET); // Fake ivar lookup; this should really be part of // LookupParsedName. @@ -4799,7 +4796,7 @@ std::unique_ptr Sema::makeTypoCorrectionConsumer( const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, DeclContext *MemberContext, bool EnteringContext, - const ObjCObjectPointerType *OPT, bool ErrorRecovery) { + const ObjCObjectPointerType *OPT, bool ErrorRecovery, QualType ET) { if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking || DisableTypoCorrection) @@ -4866,7 +4863,7 @@ std::unique_ptr Sema::makeTypoCorrectionConsumer( std::unique_ptr ClonedCCC = CCC.clone(); auto Consumer = std::make_unique( *this, TypoName, LookupKind, S, SS, std::move(ClonedCCC), MemberContext, - EnteringContext); + EnteringContext, ET); // Perform name lookup to find visible, similarly-named entities. bool IsUnqualifiedLookup = false; @@ -4919,7 +4916,7 @@ std::unique_ptr Sema::makeTypoCorrectionConsumer( AddKeywordsToConsumer(*this, *Consumer, S, *Consumer->getCorrectionValidator(), - SS && SS->isNotEmpty()); + (SS && SS->isNotEmpty() || !ET.isNull())); // Build the NestedNameSpecifiers for the KnownNamespaces, if we're going // to search those namespaces. @@ -5110,10 +5107,10 @@ TypoExpr *Sema::CorrectTypoDelayed( Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode, DeclContext *MemberContext, bool EnteringContext, - const ObjCObjectPointerType *OPT) { + const ObjCObjectPointerType *OPT, QualType ET) { auto Consumer = makeTypoCorrectionConsumer(TypoName, LookupKind, S, SS, CCC, MemberContext, EnteringContext, - OPT, Mode == CTK_ErrorRecovery); + OPT, Mode == CTK_ErrorRecovery, ET); // Give the external sema source a chance to correct the typo. TypoCorrection ExternalTypo; diff --git a/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs b/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs index 274e6134f102..9df3ea945f47 100644 --- a/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs @@ -1,11 +1,12 @@ // RUN: %clang_cc1 -verify %s -int getA() { +int getA() { // expected-note {{'getA' declared here}} + // expected-note@-1 {{'getA' declared here}} return 1; } int main() { - int (*fp)() = int::getA; // expected-error {{use of undeclared identifier 'getA'}} - int (*fp1)() = &int::getA; // expected-error {{use of undeclared identifier 'getA'}} + int (*fp)() = int::getA; // expected-error {{no member named 'getA' in int; did you mean simply 'getA'?}} + int (*fp1)() = &int::getA; // expected-error {{no member named 'getA' in int; did you mean simply 'getA'?}} return 0; } \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs b/clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs index 595e5db3448a..aeac34d4f276 100644 --- a/clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs +++ b/clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs @@ -5,12 +5,13 @@ enum E { X4 }; -int getA() { +int getA() { // expected-note {{'getA' declared here}} + // expected-note@-1 {{'getA' declared here}} return 1; } int main() { - int (*fp)() = enum E::getA; // expected-error {{use of undeclared identifier 'getA'}} - int (*fp1)() = &enum E::getA; // expected-error {{use of undeclared identifier 'getA'}} + int (*fp)() = enum E::getA; // expected-error {{no member named 'getA' in 'enum E'; did you mean simply 'getA'?}} + int (*fp1)() = &enum E::getA; // expected-error {{no member named 'getA' in 'enum E'; did you mean simply 'getA'?}} return 0; } \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs b/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs index 5849ca25dfcc..88694445271e 100644 --- a/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs +++ b/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs @@ -4,12 +4,13 @@ struct Foo { int a; }; -int getA() { +int getA() { // expected-note {{'getA' declared here}} + // expected-note@-1 {{'getA' declared here}} return 1; } int main() { - int (*fp)() = struct Foo::getA; // expected-error {{use of undeclared identifier 'getA'}} - int (*fp1)() = &struct Foo::getA; // expected-error {{use of undeclared identifier 'getA'}} + int (*fp)() = struct Foo::getA; // expected-error {{no member named 'getA' in 'struct Foo'; did you mean simply 'getA'?}} + int (*fp1)() = &struct Foo::getA; // expected-error {{no member named 'getA' in 'struct Foo'; did you mean simply 'getA'?}} return 0; } diff --git a/clang/test/BSC/Method/Struct/struct_static_function_not_found.cbs b/clang/test/BSC/Method/Struct/struct_static_function_not_found.cbs new file mode 100644 index 000000000000..d1ad48c47d5b --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_static_function_not_found.cbs @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA() { // expected-note {{'getA' declared here}} + return 1; +} + + +int main() { + struct Foo::getB(); // expected-error {{no member named 'getB' in 'struct Foo'; did you mean 'getA'?}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs b/clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs index 8993ac904fb7..f0bffb77b1f3 100644 --- a/clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs +++ b/clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs @@ -6,12 +6,13 @@ union SimpleUnion { char uc; }; -int getA() { +int getA() { // expected-note {{'getA' declared here}} + // expected-note@-1 {{'getA' declared here}} return 1; } int main() { - int (*fp)() = union SimpleUnion::getA; // expected-error {{use of undeclared identifier 'getA'}} - int (*fp1)() = &union SimpleUnion::getA; // expected-error {{use of undeclared identifier 'getA'}} + int (*fp)() = union SimpleUnion::getA; // expected-error {{no member named 'getA' in 'union SimpleUnion'; did you mean simply 'getA'?}} + int (*fp1)() = &union SimpleUnion::getA; // expected-error {{no member named 'getA' in 'union SimpleUnion'; did you mean simply 'getA'?}} return 0; } \ No newline at end of file -- Gitee From 3aed0a07b88bdefd46ae9fa1a02a13b591d9ebb7 Mon Sep 17 00:00:00 2001 From: zhaoxuhui Date: Tue, 7 Mar 2023 19:15:40 +0800 Subject: [PATCH 2/4] [BSC] fixed error message of Enum and BuiltinType if the function to be called cannot be found --- clang/lib/Sema/SemaExprMember.cpp | 75 ++++++++++++------- .../int_instance_function_no_member.cbs | 3 +- .../int_instance_function_no_member2.cbs | 11 +++ .../Enum/enum_instance_function_not_found.cbs | 2 - 4 files changed, 62 insertions(+), 29 deletions(-) create mode 100644 clang/test/BSC/Method/BuiltInType/int_instance_function_no_member2.cbs diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 30a7a2258383..b3d8b479ddf3 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1089,9 +1089,19 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, if (R.empty()) { // Rederive where we looked up. - DeclContext *DC = (SS.isSet() - ? computeDeclContext(SS, false) + DeclContext *DC = nullptr; + const char *BuiltinName = ""; + if (const BuiltinType *BTy = BaseType->getAs()) { + BuiltinName = BTy->getNameAsCString(getPrintingPolicy()); + } else if (const EnumType *ETy = BaseType->getAs()) { + if (getASTContext().BSCDeclContextMap.find(ETy) != + getASTContext().BSCDeclContextMap.end()) { + DC = getASTContext().BSCDeclContextMap[ETy]; + } + } else { + DC = (SS.isSet() ? computeDeclContext(SS, false) : BaseType->castAs()->getDecl()); + } if (ExtraArgs) { ExprResult RetryExpr; @@ -1112,15 +1122,27 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, RetryExpr = ExprError(); } if (RetryExpr.isUsable()) { - Diag(OpLoc, diag::err_no_member_overloaded_arrow) - << MemberName << DC << FixItHint::CreateReplacement(OpLoc, "->"); - return RetryExpr; + if (DC) { + Diag(OpLoc, diag::err_no_member_overloaded_arrow) + << MemberName << DC << FixItHint::CreateReplacement(OpLoc, "->"); + return RetryExpr; + } else { + Diag(OpLoc, diag::err_no_member_overloaded_arrow) + << MemberName << BuiltinName + << FixItHint::CreateReplacement(OpLoc, "->"); + return RetryExpr; + } } } - - Diag(R.getNameLoc(), diag::err_no_member) - << MemberName << DC - << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); + if (DC) { + Diag(R.getNameLoc(), diag::err_no_member) + << MemberName << DC + << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); + } else { + Diag(R.getNameLoc(), diag::err_no_member) + << MemberName << BuiltinName + << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); + } return ExprError(); } @@ -1431,9 +1453,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, if (S.getLangOpts().BSC) { if (const BuiltinType *BTy = BaseType->getAs()) { + TypoExpr *TE = nullptr; if (S.getASTContext().BSCDeclContextMap.find(BTy) != S.getASTContext().BSCDeclContextMap.end()) { - TypoExpr *TE = nullptr; auto DeclContext = S.getASTContext().BSCDeclContextMap[BTy]; // TODO: add assert RecordDecl *Rdecl = dyn_cast(DeclContext); @@ -1441,35 +1463,38 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy, OpLoc, IsArrow, SS, HasTemplateArgs, TemplateKWLoc, TE)) return ExprError(); - - // Returning valid-but-null is how we indicate to the caller that - // the lookup result was filled in. If typo correction was attempted and - // failed, the lookup result will have been cleared--that combined with - // the valid-but-null ExprResult will trigger the appropriate - // diagnostics. - return ExprResult(TE); } + // Returning valid-but-null is how we indicate to the caller that + // the lookup result was filled in. If typo correction was attempted and + // failed, the lookup result will have been cleared--that combined with + // the valid-but-null ExprResult will trigger the appropriate + // diagnostics. + return ExprResult(TE); } if (const EnumType *ETy = BaseType->getAs()) { + TypoExpr *TE = nullptr; if (S.getASTContext().BSCDeclContextMap.find(ETy) != S.getASTContext().BSCDeclContextMap.end()) { - TypoExpr *TE = nullptr; // TODO: add assert if (LookupMemberExprInEnum(S, R, BaseExpr.get(), ETy, OpLoc, IsArrow, SS, TE)) return ExprError(); if (!R.empty() && - dyn_cast(R.getFoundDecl()) != nullptr) { - // Returning valid-but-null is how we indicate to the caller that - // the lookup result was filled in. If typo correction was attempted - // and failed, the lookup result will have been cleared--that combined - // with the valid-but-null ExprResult will trigger the appropriate - // diagnostics. - return ExprResult(TE); + dyn_cast(R.getFoundDecl()) == nullptr) { + S.Diag(OpLoc, diag::err_typecheck_member_reference_struct_union) + << BaseType << BaseExpr.get()->getSourceRange() << MemberLoc; + + return ExprError(); } } + // Returning valid-but-null is how we indicate to the caller that + // the lookup result was filled in. If typo correction was attempted + // and failed, the lookup result will have been cleared--that combined + // with the valid-but-null ExprResult will trigger the appropriate + // diagnostics. + return ExprResult(TE); } } diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member.cbs index 54fc85d083ff..8715d1a5348a 100644 --- a/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member.cbs @@ -3,7 +3,6 @@ int main() { int x = 1; - x.increase(); // expected-error {{member reference base type 'int' is not a structure or union}} - // TODO: are we able to optimise this diagnostic + x.increase(); // expected-error {{no member named 'increase' in int}} return 0; } \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member2.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member2.cbs new file mode 100644 index 000000000000..4f1c9b707c5d --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member2.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +int int::getA() { + return 1; +} + +int main() { + int x = 1; + x.increase(); // expected-error {{no member named 'increase' in int}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_not_found.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_not_found.cbs index 59fd07cb2c29..4789c86feca2 100644 --- a/clang/test/BSC/Method/Enum/enum_instance_function_not_found.cbs +++ b/clang/test/BSC/Method/Enum/enum_instance_function_not_found.cbs @@ -12,7 +12,5 @@ int enum E::getA(enum E* this) { int main() { enum E foo = X3; foo.getB(); // expected-error {{no member named 'getB' in 'enum E'}} - // expected-error@-1 {{member reference base type 'enum E' is not a structure or union}} - // TODO: are we able to improve this diagnostic message? return 0; } \ No newline at end of file -- Gitee From b1f50f5dd700e8b229e4d4c55bc5fa1249331518 Mon Sep 17 00:00:00 2001 From: zhaoxuhui Date: Tue, 7 Mar 2023 19:17:41 +0800 Subject: [PATCH 3/4] [BSC] add note message for calling member function without 'this' parameter in the way of '.' or '->' --- .../clang/Basic/DiagnosticSemaKinds.td | 1 + clang/lib/Sema/SemaExprMember.cpp | 39 ++++++++++++++----- .../Method/BuiltInType/int_function_call.cbs | 6 ++- .../BSC/Method/Enum/enum_function_call.cbs | 2 + .../Method/Struct/struct_function_call.cbs | 2 + .../BSC/Method/Union/union_function_call.cbs | 2 + 6 files changed, 40 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 80600c146673..eb3346e572a6 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -16,6 +16,7 @@ def note_previous_decl : Note<"%0 declared here">; def note_entity_declared_at : Note<"%0 declared here">; def note_callee_decl : Note<"%0 declared here">; def note_defined_here : Note<"%0 defined here">; +def note_no_this_parameter : Note<"found the following member function %0 which doesn't have a 'this' parameter">; // For loop analysis def warn_variables_not_in_loop_body : Warning< diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index b3d8b479ddf3..d5e844acce0a 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1255,19 +1255,38 @@ 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()]; + const char *BuiltinName = ""; + QualType ET = MemberFn->getExtendedType(); + DeclContext *DC = nullptr; + if (!ET.isNull()) { + if (const BuiltinType *BTy = ET->getAs()) + BuiltinName = BTy->getNameAsCString(getPrintingPolicy()); + else + DC = getASTContext() + .BSCDeclContextMap[ET.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, "::"); + if (DC) { + 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, "::"); + } else { + if (IsArrow) + Diag(OpLoc, diag::err_no_member_on_arrow) + << MemberName << BuiltinName + << FixItHint::CreateReplacement(OpLoc, "::"); + else + Diag(OpLoc, diag::err_no_member_on_period) + << MemberName << BuiltinName + << FixItHint::CreateReplacement(OpLoc, "::"); + } + Diag(OpLoc, diag::note_no_this_parameter) << MemberName; } } diff --git a/clang/test/BSC/Method/BuiltInType/int_function_call.cbs b/clang/test/BSC/Method/BuiltInType/int_function_call.cbs index d06846e9da52..da816d1e0ee8 100644 --- a/clang/test/BSC/Method/BuiltInType/int_function_call.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_function_call.cbs @@ -6,7 +6,9 @@ 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 '->'?}} + x.increase(); // expected-error {{no instance member named 'increase' in int; did you mean to use '::' instead of '.'?}} + // expected-note@-1 {{found the following member function 'increase' which doesn't have a 'this' parameter}} + y->increase(); // expected-error {{no instance member named 'increase' in int; did you mean to use '::' instead of '->'?}} + // expected-note@-1 {{found the following member function 'increase' which doesn't have a 'this' parameter}} 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 index f8cdb1f0366c..5cfbe9b8d576 100644 --- a/clang/test/BSC/Method/Enum/enum_function_call.cbs +++ b/clang/test/BSC/Method/Enum/enum_function_call.cbs @@ -13,6 +13,8 @@ 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 '.'?}} + // expected-note@-1 {{found the following member function 'getA' which doesn't have a 'this' parameter}} f->getA(); // expected-error {{no instance member named 'getA' in 'enum E'; did you mean to use '::' instead of '->'?}} + // expected-note@-1 {{found the following member function 'getA' which doesn't have a 'this' parameter}} 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 index 7ae8e560c758..46d306d734d0 100644 --- a/clang/test/BSC/Method/Struct/struct_function_call.cbs +++ b/clang/test/BSC/Method/Struct/struct_function_call.cbs @@ -11,6 +11,8 @@ 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 '.'?}} + // expected-note@-1 {{found the following member function 'getA' which doesn't have a 'this' parameter}} f->getA(); // expected-error {{no instance member named 'getA' in 'struct Foo'; did you mean to use '::' instead of '->'?}} + // expected-note@-1 {{found the following member function 'getA' which doesn't have a 'this' parameter}} 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 index 4ef37fe8dd1e..7183d5946844 100644 --- a/clang/test/BSC/Method/Union/union_function_call.cbs +++ b/clang/test/BSC/Method/Union/union_function_call.cbs @@ -14,6 +14,8 @@ 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 '.'?}} + // expected-note@-1 {{found the following member function 'getA' which doesn't have a 'this' parameter}} f->getA(); // expected-error {{no instance member named 'getA' in 'union SimpleUnion'; did you mean to use '::' instead of '->'?}} + // expected-note@-1 {{found the following member function 'getA' which doesn't have a 'this' parameter}} return 0; } \ No newline at end of file -- Gitee From 75e93a6f20275db24a1c1a626630c82288ac86a8 Mon Sep 17 00:00:00 2001 From: zhaoxuhui Date: Thu, 9 Mar 2023 20:27:38 +0800 Subject: [PATCH 4/4] fix review suggestions --- .../clang/Basic/DiagnosticSemaKinds.td | 6 ++-- clang/lib/Sema/SemaExpr.cpp | 13 ++++---- clang/lib/Sema/SemaExprMember.cpp | 32 +++++++------------ .../Method/BuiltInType/int_function_call.cbs | 4 +-- .../int_function_pointer_undeclared.cbs | 4 +-- .../int_instance_function_no_member.cbs | 2 +- .../int_instance_function_no_member2.cbs | 2 +- 7 files changed, 26 insertions(+), 37 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index eb3346e572a6..2ed51821f196 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6455,10 +6455,8 @@ 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_no_instance_member : Error< + "no instance member named %0 in %1; did you mean to use '::' instead of '%select{.|->}2'?">; def err_member_not_yet_instantiated : Error< "no member %0 in %1; it has not yet been instantiated">; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 6cbbfac46104..6486853a0417 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2134,12 +2134,13 @@ static void emitEmptyLookupTypoDiagnostic( Ctx = ETy->getDecl(); } else if (const BuiltinType *BTy = dyn_cast(BasedType)) { // builtin type - SemaRef.diagnoseTypo( - TC, - SemaRef.PDiag(diag::err_no_member_suggest) - << Typo << BTy->getNameAsCString(SemaRef.getPrintingPolicy()) - << DroppedSpecifier << SS.getRange(), - SemaRef.PDiag(NoteID)); + std::string BuiltinName = + BTy->getNameAsCString(SemaRef.getPrintingPolicy()); + SemaRef.diagnoseTypo(TC, + SemaRef.PDiag(diag::err_no_member_suggest) + << Typo << "type '" + BuiltinName + "'" + << DroppedSpecifier << SS.getRange(), + SemaRef.PDiag(NoteID)); return; } } diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index d5e844acce0a..ec3e761a279c 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1090,7 +1090,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, if (R.empty()) { // Rederive where we looked up. DeclContext *DC = nullptr; - const char *BuiltinName = ""; + std::string BuiltinName = ""; if (const BuiltinType *BTy = BaseType->getAs()) { BuiltinName = BTy->getNameAsCString(getPrintingPolicy()); } else if (const EnumType *ETy = BaseType->getAs()) { @@ -1128,7 +1128,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, return RetryExpr; } else { Diag(OpLoc, diag::err_no_member_overloaded_arrow) - << MemberName << BuiltinName + << MemberName << "type '" + BuiltinName + "'" << FixItHint::CreateReplacement(OpLoc, "->"); return RetryExpr; } @@ -1140,7 +1140,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); } else { Diag(R.getNameLoc(), diag::err_no_member) - << MemberName << BuiltinName + << MemberName << "type '" + BuiltinName + "'" << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); } return ExprError(); @@ -1255,7 +1255,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, QualType type; valueKind = VK_LValue; type = MemberFn->getType(); - const char *BuiltinName = ""; + std::string BuiltinName = ""; QualType ET = MemberFn->getExtendedType(); DeclContext *DC = nullptr; if (!ET.isNull()) { @@ -1268,25 +1268,15 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // it can only be called through '::'. if (!MemberFn->getHasThisParam()) { if (DC) { - 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, "::"); + Diag(OpLoc, diag::err_no_instance_member) + << MemberName << DC << int(IsArrow) + << FixItHint::CreateReplacement(OpLoc, "::"); } else { - if (IsArrow) - Diag(OpLoc, diag::err_no_member_on_arrow) - << MemberName << BuiltinName - << FixItHint::CreateReplacement(OpLoc, "::"); - else - Diag(OpLoc, diag::err_no_member_on_period) - << MemberName << BuiltinName - << FixItHint::CreateReplacement(OpLoc, "::"); + Diag(OpLoc, diag::err_no_instance_member) + << MemberName << "type '" + BuiltinName + "'" << int(IsArrow) + << FixItHint::CreateReplacement(OpLoc, "::"); } - Diag(OpLoc, diag::note_no_this_parameter) << MemberName; + Diag(MemberLoc, diag::note_no_this_parameter) << MemberName; } } diff --git a/clang/test/BSC/Method/BuiltInType/int_function_call.cbs b/clang/test/BSC/Method/BuiltInType/int_function_call.cbs index da816d1e0ee8..295533823727 100644 --- a/clang/test/BSC/Method/BuiltInType/int_function_call.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_function_call.cbs @@ -6,9 +6,9 @@ void int::increase() { int main() { int x = 1; int *y = &x; - x.increase(); // expected-error {{no instance member named 'increase' in int; did you mean to use '::' instead of '.'?}} + x.increase(); // expected-error {{no instance member named 'increase' in type 'int'; did you mean to use '::' instead of '.'?}} // expected-note@-1 {{found the following member function 'increase' which doesn't have a 'this' parameter}} - y->increase(); // expected-error {{no instance member named 'increase' in int; did you mean to use '::' instead of '->'?}} + y->increase(); // expected-error {{no instance member named 'increase' in type 'int'; did you mean to use '::' instead of '->'?}} // expected-note@-1 {{found the following member function 'increase' which doesn't have a 'this' parameter}} return 0; } \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs b/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs index 9df3ea945f47..123e352ba820 100644 --- a/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs @@ -6,7 +6,7 @@ int getA() { // expected-note {{'getA' declared here}} } int main() { - int (*fp)() = int::getA; // expected-error {{no member named 'getA' in int; did you mean simply 'getA'?}} - int (*fp1)() = &int::getA; // expected-error {{no member named 'getA' in int; did you mean simply 'getA'?}} + int (*fp)() = int::getA; // expected-error {{no member named 'getA' in type 'int'; did you mean simply 'getA'?}} + int (*fp1)() = &int::getA; // expected-error {{no member named 'getA' in type 'int'; did you mean simply 'getA'?}} return 0; } \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member.cbs index 8715d1a5348a..0281dac776b7 100644 --- a/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member.cbs @@ -3,6 +3,6 @@ int main() { int x = 1; - x.increase(); // expected-error {{no member named 'increase' in int}} + x.increase(); // expected-error {{no member named 'increase' in type 'int'}} return 0; } \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member2.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member2.cbs index 4f1c9b707c5d..c99483eedf81 100644 --- a/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member2.cbs +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_no_member2.cbs @@ -6,6 +6,6 @@ int int::getA() { int main() { int x = 1; - x.increase(); // expected-error {{no member named 'increase' in int}} + x.increase(); // expected-error {{no member named 'increase' in type 'int'}} return 0; } \ No newline at end of file -- Gitee