From 9f6f6335cca6c43e564338b41fe5d7d69ba05951 Mon Sep 17 00:00:00 2001 From: yangdiangzb Date: Thu, 23 Feb 2023 10:50:13 +0000 Subject: [PATCH 1/8] [BSC] bugfix for unqualified call --- clang/lib/Frontend/CompilerInvocation.cpp | 2 +- clang/lib/Sema/SemaDecl.cpp | 5 +++++ clang/test/BSC/Driver/std_option.cbs | 12 ++++++++++++ .../BSC/Method/Struct/struct_toplevel_func.cbs | 18 ++++++++++++++++++ .../Struct/struct_toplevel_func_not_found.cbs | 12 ++++++++++++ 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 clang/test/BSC/Driver/std_option.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_toplevel_func.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_toplevel_func_not_found.cbs diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 03f75ca2d0e2..8d4235cc2ec2 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2125,7 +2125,7 @@ static bool IsInputCompatibleWithStandard(InputKind IK, return S.getLanguage() == Language::CXX || S.getLanguage() == Language::HIP; case Language::BSC: - return S.getLanguage() == Language::BSC; + return S.getLanguage() == Language::C || S.getLanguage() == Language::BSC; case Language::Asm: // Accept (and ignore) all -std= values. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 23c28150ae24..1fbf8c3ad642 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1479,6 +1479,11 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { if (getLangOpts().CPlusPlus && D->isOutOfLine() && !S->getFnParent()) return; + // BSCMethodDecls shouldn't be pushed into scope in BSC. + if (getLangOpts().BSC && isa(D)) { + return; + } + // Template instantiations should also not be pushed into scope. if (isa(D) && cast(D)->isFunctionTemplateSpecialization()) diff --git a/clang/test/BSC/Driver/std_option.cbs b/clang/test/BSC/Driver/std_option.cbs new file mode 100644 index 000000000000..d60bdae7ad7d --- /dev/null +++ b/clang/test/BSC/Driver/std_option.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c11 -verify %s +// RUN: %clang_cc1 -std=c89 -verify %s +// RUN: %clang_cc1 -std=c99 -verify %s +// RUN: %clang_cc1 -std=c17 -verify %s + +struct Foo { +}; +// expected-error@+2 {{cannot combine with previous 'int' declaration specifier}} +// expected-error@+1 {{expected identifier or '('}} +int struct Foo::getA(struct Foo* this) { + return 1; +} diff --git a/clang/test/BSC/Method/Struct/struct_toplevel_func.cbs b/clang/test/BSC/Method/Struct/struct_toplevel_func.cbs new file mode 100644 index 000000000000..268989fa775b --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_toplevel_func.cbs @@ -0,0 +1,18 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// expected-no-diagnostics + +struct F { +}; + +int struct F::increase() { + return 2; +} + +int increase() { + return 0; +} + +int main() { + return increase(); +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_toplevel_func_not_found.cbs b/clang/test/BSC/Method/Struct/struct_toplevel_func_not_found.cbs new file mode 100644 index 000000000000..1086c2c0007c --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_toplevel_func_not_found.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -verify %s + +struct F { +}; +void struct F::increase(struct F* this) { + +} + +int main() { + increase(); // expected-warning {{implicit declaration of function 'increase' is invalid in C99}} + return 0; +} \ No newline at end of file -- Gitee From 7dd378d1e2f41b14ab85b5eee6dbc09eb46eab06 Mon Sep 17 00:00:00 2001 From: Healing Date: Thu, 23 Feb 2023 11:25:25 +0000 Subject: [PATCH 2/8] [BSC] support mangle for BSCMethod --- clang/lib/AST/Mangle.cpp | 12 ++++++++++++ clang/lib/Serialization/ASTReaderDecl.cpp | 3 ++- clang/lib/Serialization/ASTWriterDecl.cpp | 9 ++++++--- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp index 3282fcbd584f..3e4a497aef98 100644 --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -107,6 +107,10 @@ static CCMangling getCallingConvMangling(const ASTContext &Context, bool MangleContext::shouldMangleDeclName(const NamedDecl *D) { const ASTContext &ASTContext = getASTContext(); + const auto *MD = dyn_cast(D); + if (MD && !MD->getExtendedType().isNull()) + return true; + CCMangling CC = getCallingConvMangling(ASTContext, D); if (CC != CCM_Other) return true; @@ -171,6 +175,14 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) { return; } + const auto *MD = dyn_cast(D); + if (MD && !MD->getExtendedType().isNull()) { + Out << "_ZN"; + mangleTypeName(MD->getExtendedType(), Out); + Out << D->getIdentifier()->getName(); + return; + } + bool MCXX = shouldMangleCXXName(D); const TargetInfo &TI = Context.getTargetInfo(); if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 91ec268465da..e2dc84e848f5 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1962,7 +1962,8 @@ void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { void ASTDeclReader::VisitBSCMethodDecl(BSCMethodDecl *D) { VisitFunctionDecl(D); - Record.readInt(); + D->setExtendedType(Record.readQualType()); + D->setHasThisParam(Record.readInt()); } void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index ca8d5fd323ea..4fb45e45c672 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1368,7 +1368,8 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { void ASTDeclWriter::VisitBSCMethodDecl(BSCMethodDecl *D) { VisitFunctionDecl(D); - Record.AddDeclRef(D); + Record.AddTypeRef(D->getExtendedType()); + Record.push_back(D->getHasThisParam()); if (D->getDeclContext() == D->getLexicalDeclContext() && D->getFirstDecl() == D->getMostRecentDecl() && @@ -2338,12 +2339,14 @@ void ASTWriter::WriteDeclAbbrevs() { // (nearly) all the remaining (variable number of) fields in the same way. // // This is the function template information if any, then - // NumParams and Params[] from FunctionDecl, and - // NumOverriddenMethods, OverriddenMethods[] from BSCMethodDecl. + // NumParams and Params[] from FunctionDecl // // Add an AbbrevOp for 'size then elements' and use it here. Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); + // BSCMethodDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ExtendedType + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasThisParam DeclBSCMethodAbbrev = Stream.EmitAbbrev(std::move(Abv)); // Abbreviation for EXPR_DECL_REF -- Gitee From 9627abb29a7372c364960bfa2a4679eeb5c5644f Mon Sep 17 00:00:00 2001 From: yangdian Date: Fri, 24 Feb 2023 17:30:15 +0800 Subject: [PATCH 3/8] [BSC] auto format code --- clang/include/clang/AST/ASTContext.h | 2 +- clang/include/clang/AST/DeclCXX.h | 20 +++-- clang/include/clang/Parse/Parser.h | 8 +- .../clang/Parse/RAIIObjectsForParser.h | 15 ++-- clang/include/clang/Sema/DeclSpec.h | 10 ++- clang/include/clang/Sema/Sema.h | 2 +- clang/include/clang/Sema/Template.h | 8 +- clang/lib/AST/Decl.cpp | 3 +- clang/lib/AST/DeclCXX.cpp | 20 ++--- clang/lib/Parse/ParseDecl.cpp | 36 ++++----- clang/lib/Sema/SemaDecl.cpp | 19 +++-- clang/lib/Sema/SemaExpr.cpp | 73 +++++++++++-------- clang/lib/Sema/SemaExprMember.cpp | 49 +++++++------ clang/lib/Sema/SemaLookup.cpp | 9 +-- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 +- clang/lib/Sema/SemaType.cpp | 26 ++++--- clang/lib/Serialization/ASTWriterDecl.cpp | 67 ++++++++--------- 17 files changed, 191 insertions(+), 178 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index d24f00694f7f..359f666c7f49 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -447,7 +447,7 @@ public: using TemplateOrSpecializationInfo = llvm::PointerUnion; - mutable llvm::DenseMap BSCDeclContextMap; + mutable llvm::DenseMap BSCDeclContextMap; private: friend class ASTDeclReader; diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 5da1097e8a7a..499320e554df 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1945,21 +1945,19 @@ protected: } public: - static BSCMethodDecl *Create(ASTContext &C, DeclContext *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, StorageClass SC, - bool isInline, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, - Expr *TrailingRequiresClause = nullptr); + static BSCMethodDecl * + Create(ASTContext &C, DeclContext *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + StorageClass SC, bool isInline, ConstexprSpecKind ConstexprKind, + SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr); static BSCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); - bool getHasThisParam() const { - return hasThisParam; - } + bool getHasThisParam() const { return hasThisParam; } void setHasThisParam(bool hasThisParam) { this->hasThisParam = hasThisParam; } QualType getExtendedType() const { return ExtendedType; } - void setExtendedType(QualType ExtendedType) { this->ExtendedType = ExtendedType; } + void setExtendedType(QualType ExtendedType) { + this->ExtendedType = ExtendedType; + } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index ad9bb0a6b91f..eb4a0488341d 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2921,11 +2921,9 @@ private: Declarator &D, SmallVectorImpl &ParamInfo); void ParseParameterDeclarationClause( - DeclaratorContext DeclaratorContext, - ParsedAttributes &attrs, - SmallVectorImpl &ParamInfo, - SourceLocation &EllipsisLoc, - const Type *typePtr = nullptr); + DeclaratorContext DeclaratorContext, ParsedAttributes &attrs, + SmallVectorImpl &ParamInfo, + SourceLocation &EllipsisLoc, const Type *typePtr = nullptr); void ParseBracketDeclarator(Declarator &D); void ParseMisplacedBracketDeclarator(Declarator &D); diff --git a/clang/include/clang/Parse/RAIIObjectsForParser.h b/clang/include/clang/Parse/RAIIObjectsForParser.h index e02815bfe54c..7f8040d78b90 100644 --- a/clang/include/clang/Parse/RAIIObjectsForParser.h +++ b/clang/include/clang/Parse/RAIIObjectsForParser.h @@ -202,23 +202,18 @@ namespace clang { public: BSCScopeSpec(Parser &P) - : DeclSpec(P.getAttrFactory()), - ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {} + : DeclSpec(P.getAttrFactory()), + ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {} BSCScopeSpec(Parser &P, ParsingDeclRAIIObject *RAII) - : DeclSpec(P.getAttrFactory()), - ParsingRAII(P, RAII) {} + : DeclSpec(P.getAttrFactory()), ParsingRAII(P, RAII) {} const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const { return ParsingRAII.getDelayedDiagnosticPool(); } - void complete(Decl *D) { - ParsingRAII.complete(D); - } + void complete(Decl *D) { ParsingRAII.complete(D); } - void abort() { - ParsingRAII.abort(); - } + void abort() { ParsingRAII.abort(); } }; /// A class for parsing a declarator. diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 11c359717ff8..e797da753ad7 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1824,7 +1824,7 @@ class Declarator { private: const DeclSpec &DS; CXXScopeSpec SS; - DeclSpec *BSCDS=nullptr; + DeclSpec *BSCDS = nullptr; QualType ExtendedType; // BSC only UnqualifiedId Name; @@ -1933,13 +1933,15 @@ public: /// declared with. const DeclSpec &getDeclSpec() const { return DS; } - /// getBSCScopeSpec - Return the BSCMethod declaration-specifier that this declarator was - /// declared with. + /// getBSCScopeSpec - Return the BSCMethod declaration-specifier that this + /// declarator was declared with. DeclSpec *getBSCScopeSpec() { return BSCDS; } void setBSCScopeSpec(DeclSpec *ScopeSpec) { BSCDS = ScopeSpec; } QualType getExtendedType() const { return ExtendedType; } - void setExtendedType(QualType ExtendedType) { this->ExtendedType = ExtendedType; } + void setExtendedType(QualType ExtendedType) { + this->ExtendedType = ExtendedType; + } /// getMutableDeclSpec - Return a non-const version of the DeclSpec. This /// should be used with extreme care: declspecs can often be shared between diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d9c176327317..5809edddd755 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11313,7 +11313,7 @@ public: bool AllowExplicit = false, bool IsListInitialization = false, bool IsBSCInstanceFunc = false, - CallExpr* Call = nullptr); + CallExpr *Call = nullptr); // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but // will create a runtime trap if the resulting type is not a POD type. diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index 880412cd3725..8c3fc70d26be 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -532,10 +532,10 @@ enum class TemplateSubstitutionKind : char { ClassScopeSpecializationArgs = llvm::None, RewriteKind RK = RewriteKind::None); Decl *VisitBSCMethodDecl(BSCMethodDecl *D, - TemplateParameterList *TemplateParams, - Optional - ClassScopeSpecializationArgs = llvm::None, - RewriteKind RK = RewriteKind::None); + TemplateParameterList *TemplateParams, + Optional + ClassScopeSpecializationArgs = llvm::None, + RewriteKind RK = RewriteKind::None); Decl *VisitFunctionDecl(FunctionDecl *D, TemplateParameterList *TemplateParams, RewriteKind RK = RewriteKind::None); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 36c0d620b473..9c4b8959111f 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2074,7 +2074,8 @@ static bool isDeclExternC(const T &D) { // language linkage or no language linkage. const DeclContext *DC = D.getDeclContext(); if (DC->isRecord()) { - assert(D.getASTContext().getLangOpts().CPlusPlus || D.getASTContext().getLangOpts().BSC); + assert(D.getASTContext().getLangOpts().CPlusPlus || + D.getASTContext().getLangOpts().BSC); return false; } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 1386504b436d..ec71d0fabe90 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2190,18 +2190,14 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD, return FinalOverriders.size() == 1 ? FinalOverriders.front() : nullptr; } -BSCMethodDecl *BSCMethodDecl::Create(ASTContext &C, DeclContext *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - StorageClass SC, bool isInline, - ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, - Expr *TrailingRequiresClause) { - return new (C, RD) - BSCMethodDecl(BSCMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC, - isInline, ConstexprKind, EndLocation, - TrailingRequiresClause); +BSCMethodDecl *BSCMethodDecl::Create( + ASTContext &C, DeclContext *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + StorageClass SC, bool isInline, ConstexprSpecKind ConstexprKind, + SourceLocation EndLocation, Expr *TrailingRequiresClause) { + return new (C, RD) BSCMethodDecl(BSCMethod, C, RD, StartLoc, NameInfo, T, + TInfo, SC, isInline, ConstexprKind, + EndLocation, TrailingRequiresClause); } BSCMethodDecl *BSCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 20b40259a8c8..22be56c90274 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1977,10 +1977,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, &LateParsedAttrs); if (!D.getExtendedType().isNull()) { if (auto *MD = dyn_cast(TheDecl)) { - MD->setExtendedType(D.getExtendedType()); + MD->setExtendedType(D.getExtendedType()); MD->setHasThisParam(D.hasThisParam); } - } + } return Actions.ConvertDeclToDeclGroup(TheDecl); } @@ -2043,7 +2043,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, SmallVector DeclsInGroup; Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes( D, ParsedTemplateInfo(), FRI); - + if (LateParsedAttrs.size() > 0) ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false); D.complete(FirstDecl); @@ -2051,7 +2051,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, if (auto FD = dyn_cast(FirstDecl)) FD->setHasThisParam(D.hasThisParam); DeclsInGroup.push_back(FirstDecl); - } + } bool ExpectSemi = Context != DeclaratorContext::ForInit; @@ -2967,8 +2967,8 @@ static void SetupFixedPointError(const LangOptions &LangOpts, void Parser::ParseBSCScopeSpecifiers(DeclSpec &DS) { bool BSCMethodFlag = true; ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, - DeclSpecContext::DSC_normal, nullptr, - BSCMethodFlag); + DeclSpecContext::DSC_normal, nullptr, + BSCMethodFlag); } /// ParseDeclarationSpecifiers @@ -3003,7 +3003,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext, LateParsedAttrList *LateAttrs, - bool BSCMethodFlag) { + bool BSCMethodFlag) { if (DS.getSourceRange().isInvalid()) { // Start the range at the current token but make the end of the range // invalid. This will make the entire range invalid unless we successfully @@ -5695,7 +5695,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D, D.setExtension(); // BSC - if (getLangOpts().BSC && (NextToken().is(tok::coloncolon) || GetLookAheadToken(2).is(tok::coloncolon))) { + if (getLangOpts().BSC && (NextToken().is(tok::coloncolon) || + GetLookAheadToken(2).is(tok::coloncolon))) { BSCScopeSpec BSS(*this); ParseBSCScopeSpecifiers(BSS); TryConsumeToken(tok::coloncolon); @@ -6543,12 +6544,12 @@ void Parser::ParseFunctionDeclarator(Declarator &D, } ParseParameterDeclarationClause(D.getContext(), FirstArgAttrs, ParamInfo, EllipsisLoc, typePtr); - } - else if (RequiresArg) + } else if (RequiresArg) Diag(Tok, diag::err_argument_required_after_attribute); - + if (ParamInfo.size() > 0) { - ParmVarDecl* PD = dyn_cast_or_null(ParamInfo.data()[0].Param); + ParmVarDecl *PD = + dyn_cast_or_null(ParamInfo.data()[0].Param); if (PD && D.getBSCScopeSpec()) D.hasThisParam = PD->isThisParam; } @@ -6799,11 +6800,9 @@ void Parser::ParseFunctionDeclaratorIdentifierList( /// [C++11] attribute-specifier-seq parameter-declaration /// void Parser::ParseParameterDeclarationClause( - DeclaratorContext DeclaratorCtx, - ParsedAttributes &FirstArgAttrs, - SmallVectorImpl &ParamInfo, - SourceLocation &EllipsisLoc, - const Type *typePtr) { + DeclaratorContext DeclaratorCtx, ParsedAttributes &FirstArgAttrs, + SmallVectorImpl &ParamInfo, + SourceLocation &EllipsisLoc, const Type *typePtr) { // Avoid exceeding the maximum function scope depth. // See https://bugs.llvm.org/show_bug.cgi?id=19607 @@ -6923,7 +6922,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); + Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator, + ParamInfo.size(), typePtr); // 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 1fbf8c3ad642..1f46f0c784df 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5769,7 +5769,8 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, D.setInvalidType(); } } else if (!D.getExtendedType().isNull()) { - DC = getASTContext().BSCDeclContextMap[D.getExtendedType().getCanonicalType().getTypePtr()]; + DC = getASTContext().BSCDeclContextMap + [D.getExtendedType().getCanonicalType().getTypePtr()]; } TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); @@ -8454,7 +8455,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier(); if (ConstexprKind == ConstexprSpecKind::Constinit) { SemaRef.Diag(D.getDeclSpec().getConstexprSpecLoc(), - diag::err_constexpr_wrong_decl_kind) + diag::err_constexpr_wrong_decl_kind) << static_cast(ConstexprKind); ConstexprKind = ConstexprSpecKind::Unspecified; D.getMutableDeclSpec().ClearConstexprSpec(); @@ -8463,9 +8464,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // This is a bsc method declaration. BSCMethodDecl *Ret = BSCMethodDecl::Create( - SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, - TInfo, SC, isInline, ConstexprKind, SourceLocation(), - TrailingRequiresClause); + SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC, + isInline, ConstexprKind, SourceLocation(), TrailingRequiresClause); return Ret; } bool HasPrototype = @@ -13617,15 +13617,18 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize, bool isThisParam = false; if (typePtr != nullptr && DeclarationName(II).getAsString() == "this") { if (ParamSize == 0) { - auto thisTypePtr = parmDeclType.getTypePtr()->getPointeeType()->getCanonicalTypeUnqualified().getTypePtr(); + auto thisTypePtr = parmDeclType.getTypePtr() + ->getPointeeType() + ->getCanonicalTypeUnqualified() + .getTypePtr(); if (typePtr == nullptr || typePtr != thisTypePtr) { Diag(D.getBeginLoc(), diag::err_type_unsupported) - << parmDeclType.getAsString(); + << parmDeclType.getAsString(); } isThisParam = true; } else { Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name) - << GetNameForDeclarator(D).getName(); + << GetNameForDeclarator(D).getName(); } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 27d3901d3d0f..aea9cacdfa53 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3411,13 +3411,13 @@ ExprResult Sema::BuildDeclarationNameExpr( // capture in OpenMP, or duplicated between host and device? valueKind = VK_LValue; break; - + case Decl::BSCMethod: // If we're referring to a method with an __unknown_anytype // result type, make the entire expression __unknown_anytype. // This should only be possible with a type written directly. - if (const FunctionProtoType *proto - = dyn_cast(VD->getType())) + if (const FunctionProtoType *proto = + dyn_cast(VD->getType())) if (proto->getReturnType() == Context.UnknownAnyTy) { type = Context.UnknownAnyTy; valueKind = VK_RValue; @@ -5781,7 +5781,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, : 0 /* function */); bool isBSCInstanceFunc = false; if (FDecl) { - BSCMethodDecl* MD = dyn_cast_or_null(FDecl); + BSCMethodDecl *MD = dyn_cast_or_null(FDecl); if (MD && MD->getHasThisParam()) { isBSCInstanceFunc = true; NumParams = NumParams - 1; @@ -5872,7 +5872,8 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, VariadicCallType CallType = getVariadicCallType(FDecl, Proto, Fn); Invalid = GatherArgumentsForCall(Call->getBeginLoc(), FDecl, Proto, 0, Args, - AllArgs, CallType, false, false, isBSCInstanceFunc, Call); + AllArgs, CallType, false, false, + isBSCInstanceFunc, Call); if (Invalid) return true; unsigned TotalNumArgs = AllArgs.size(); @@ -5888,48 +5889,58 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, SmallVectorImpl &AllArgs, VariadicCallType CallType, bool AllowExplicit, bool IsListInitialization, - bool IsBSCInstanceFunc, CallExpr* Call) { + bool IsBSCInstanceFunc, CallExpr *Call) { unsigned NumParams = Proto->getNumParams(); bool Invalid = false; size_t ArgIx = 0; - // 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. - if (IsBSCInstanceFunc) { - Expr* Callee = Call->getCallee(); - if (ImplicitCastExpr* ICE = dyn_cast(Callee)) { // Hack, if Callee is ImplicitCastExpr* - Expr* SE = ICE->getSubExpr(); - MemberExpr* Member = dyn_cast(SE); // MemberExpr foo.getA or foo->getA + // 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. + if (IsBSCInstanceFunc) { + Expr *Callee = Call->getCallee(); + if (ImplicitCastExpr *ICE = dyn_cast( + Callee)) { // Hack, if Callee is ImplicitCastExpr* + Expr *SE = ICE->getSubExpr(); + MemberExpr *Member = + dyn_cast(SE); // MemberExpr foo.getA or foo->getA if (!Member) return true; - - Expr* ImplicitArg = nullptr; + + Expr *ImplicitArg = nullptr; if (Member->isArrow()) { // foo->getA - DeclRefExpr* DRE = nullptr; - if (auto BaseExpr = dyn_cast(Member->getBase())) { + DeclRefExpr *DRE = nullptr; + if (auto BaseExpr = dyn_cast(Member->getBase())) { DRE = dyn_cast(BaseExpr->getSubExpr()); - } + } if (!DRE) return true; ImplicitArg = DeclRefExpr::Create( - this->Context, DRE->getQualifierLoc(), DRE->getTemplateKeywordLoc(), - DRE->getDecl(), DRE->refersToEnclosingVariableOrCapture(), - DRE->getNameInfo(), DRE->getType(), VK_RValue, - DRE->getFoundDecl(), nullptr); + this->Context, DRE->getQualifierLoc(), DRE->getTemplateKeywordLoc(), + DRE->getDecl(), DRE->refersToEnclosingVariableOrCapture(), + DRE->getNameInfo(), DRE->getType(), VK_RValue, DRE->getFoundDecl(), + nullptr); } else { // foo.getA - DeclRefExpr* DRE = dyn_cast(Member->getBase()); + DeclRefExpr *DRE = dyn_cast(Member->getBase()); if (!DRE) return true; - ImplicitArg = UnaryOperator::Create( - this->Context, DRE, UO_AddrOf, this->Context.getPointerType(DRE->getType()), - VK_RValue, OK_Ordinary, SourceLocation(), false, this->CurFPFeatureOverrides()); + ImplicitArg = + UnaryOperator::Create(this->Context, DRE, UO_AddrOf, + this->Context.getPointerType(DRE->getType()), + VK_RValue, OK_Ordinary, SourceLocation(), + false, this->CurFPFeatureOverrides()); } - - const FunctionProtoType* FPT = dyn_cast(Member->getType()); - auto typeQual = FPT->getParamType(0).getTypePtr()->getPointeeType().getCVRQualifiers(); + + const FunctionProtoType *FPT = + dyn_cast(Member->getType()); + auto typeQual = FPT->getParamType(0) + .getTypePtr() + ->getPointeeType() + .getCVRQualifiers(); if (typeQual & Qualifiers::Const || typeQual & Qualifiers::Volatile) { - ImplicitCastExpr* Implict = ImplicitCastExpr::Create(this->Context, FPT->getParamType(0), CK_NoOp, ImplicitArg, nullptr, VK_RValue, FPOptionsOverride()); + ImplicitCastExpr *Implict = ImplicitCastExpr::Create( + this->Context, FPT->getParamType(0), CK_NoOp, ImplicitArg, nullptr, + VK_RValue, FPOptionsOverride()); AllArgs.push_back(Implict); } else { AllArgs.push_back(ImplicitArg); diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 7c11569ddbdc..c994594ef2bd 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -635,7 +635,7 @@ private: }; // Callback to only accept typo corrections that are either a ValueDecl or a -// and are declared in the current enum or, for a C++ classes, one of its +// and are declared in the current enum or, for a C++ classes, one of its // base classes. class EnumMemberExprValidatorCCC final : public CorrectionCandidateCallback { public: @@ -835,10 +835,9 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, } static bool LookupMemberExprInEnum(Sema &SemaRef, LookupResult &R, - Expr *BaseExpr, - const EnumType *ETy, - SourceLocation OpLoc, bool IsArrow, - CXXScopeSpec &SS, TypoExpr *&TE) { + Expr *BaseExpr, const EnumType *ETy, + SourceLocation OpLoc, bool IsArrow, + CXXScopeSpec &SS, TypoExpr *&TE) { SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange(); EnumDecl *EDecl = ETy->getDecl(); @@ -1228,7 +1227,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, MemberFn, FoundDecl, /*HadMultipleCandidates=*/false, MemberNameInfo, type, valueKind, OK_Ordinary); } - + if (BSCMethodDecl *MemberFn = dyn_cast(MemberDecl)) { ExprValueKind valueKind; QualType type; @@ -1239,7 +1238,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, MemberFn, FoundDecl, /*HadMultipleCandidates=*/false, MemberNameInfo, type, valueKind, OK_Ordinary); } - + assert(!isa(MemberDecl) && "member function not C++ method?"); if (EnumConstantDecl *Enum = dyn_cast(MemberDecl)) { @@ -1416,37 +1415,43 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, } if (S.getLangOpts().BSC) { - if (const BuiltinType *BTy = BaseType->getAs()) { - if (S.getASTContext().BSCDeclContextMap.find(BTy) != S.getASTContext().BSCDeclContextMap.end()) { + if (const BuiltinType *BTy = BaseType->getAs()) { + 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); - const RecordType* RTy = dyn_cast(Rdecl->getTypeForDecl()); - if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy, OpLoc, IsArrow, SS, - HasTemplateArgs, TemplateKWLoc, TE)) + RecordDecl *Rdecl = dyn_cast(DeclContext); + const RecordType *RTy = dyn_cast(Rdecl->getTypeForDecl()); + 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. + // 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()) { - if (S.getASTContext().BSCDeclContextMap.find(ETy) != S.getASTContext().BSCDeclContextMap.end()) { + 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)) + if (LookupMemberExprInEnum(S, R, BaseExpr.get(), ETy, OpLoc, IsArrow, + SS, TE)) return ExprError(); - - if (!R.empty() && dyn_cast(R.getFoundDecl()) != nullptr) { + + 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. + // 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/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 2a5206ca6a97..2d8a65dcaae6 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -206,9 +206,8 @@ namespace { // Retrieve the set of identifier namespaces that correspond to a // specific kind of name lookup. -static inline unsigned getIDNS(Sema::LookupNameKind NameKind, - bool CPlusPlus, bool BSC, - bool Redeclaration) { +static inline unsigned getIDNS(Sema::LookupNameKind NameKind, bool CPlusPlus, + bool BSC, bool Redeclaration) { unsigned IDNS = 0; switch (NameKind) { case Sema::LookupObjCImplicitSelfParam: @@ -298,8 +297,8 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, } void LookupResult::configure() { - IDNS = getIDNS(LookupKind, getSema().getLangOpts().CPlusPlus, - getSema().getLangOpts().BSC, isForRedeclaration()); + IDNS = getIDNS(LookupKind, getSema().getLangOpts().CPlusPlus, + getSema().getLangOpts().BSC, isForRedeclaration()); // If we're looking for one of the allocation or deallocation // operators, make sure that the implicitly-declared new and delete diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index a9a77cca36a0..5cbb2039bf00 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2234,7 +2234,7 @@ Decl *TemplateDeclInstantiator::VisitBSCMethodDecl( BSCMethodDecl *D, TemplateParameterList *TemplateParams, Optional ClassScopeSpecializationArgs, RewriteKind FunctionRewriteKind) { - return VisitFunctionDecl(D, TemplateParams, FunctionRewriteKind); + return VisitFunctionDecl(D, TemplateParams, FunctionRewriteKind); } Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index c5dd268dd134..52b0fecf8551 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1282,13 +1282,15 @@ static QualType ConvertConstrainedAutoDeclSpecToType(Sema &S, DeclSpec &DS, /// to be converted, along with other associated processing state. /// \returns The type described by the declaration specifiers. This function /// never returns null. -static QualType ConvertDeclSpecToType(TypeProcessingState &state, bool BSCMethodFlag = false) { +static QualType ConvertDeclSpecToType(TypeProcessingState &state, + bool BSCMethodFlag = false) { // FIXME: Should move the logic from DeclSpec::Finish to here for validity // checking. Sema &S = state.getSema(); Declarator &declarator = state.getDeclarator(); - DeclSpec &DS = BSCMethodFlag ? *(declarator.getBSCScopeSpec()) : declarator.getMutableDeclSpec(); + DeclSpec &DS = BSCMethodFlag ? *(declarator.getBSCScopeSpec()) + : declarator.getMutableDeclSpec(); SourceLocation DeclLoc = declarator.getIdentifierLoc(); if (DeclLoc.isInvalid()) DeclLoc = DS.getBeginLoc(); @@ -1845,17 +1847,23 @@ void Sema::ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc) { Diagnoser.diagnose(*this, Loc, T); } else { D.setExtendedType(T); - const Type* BasedType = T.getCanonicalType().getTypePtr(); + const Type *BasedType = T.getCanonicalType().getTypePtr(); // build declcontext map - if (getASTContext().BSCDeclContextMap.find(BasedType) == getASTContext().BSCDeclContextMap.end()) { - if (const RecordType* RTy = dyn_cast(BasedType)) { // struct type or union type + if (getASTContext().BSCDeclContextMap.find(BasedType) == + getASTContext().BSCDeclContextMap.end()) { + if (const RecordType *RTy = dyn_cast( + BasedType)) { // struct type or union type getASTContext().BSCDeclContextMap[BasedType] = RTy->getDecl(); - } else if (const EnumType* ETy = dyn_cast(BasedType)) { // enum type + } else if (const EnumType *ETy = + dyn_cast(BasedType)) { // enum type getASTContext().BSCDeclContextMap[BasedType] = ETy->getDecl(); - } else if (const BuiltinType* BTy = dyn_cast(BasedType)){ // builtin type + } else if (const BuiltinType *BTy = + dyn_cast(BasedType)) { // builtin type std::string Prefix = "__"; - std::string BuiltinTypeName = Prefix + BTy->getNameAsCString(getPrintingPolicy()); - auto TmpRecord = getASTContext().buildImplicitRecord(StringRef(BuiltinTypeName)); + std::string BuiltinTypeName = + Prefix + BTy->getNameAsCString(getPrintingPolicy()); + auto TmpRecord = + getASTContext().buildImplicitRecord(StringRef(BuiltinTypeName)); TmpRecord->startDefinition(); TmpRecord->completeDefinition(); getASTContext().BSCDeclContextMap[BasedType] = TmpRecord; diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 4fb45e45c672..70f5002fd9d7 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1372,13 +1372,10 @@ void ASTDeclWriter::VisitBSCMethodDecl(BSCMethodDecl *D) { Record.push_back(D->getHasThisParam()); if (D->getDeclContext() == D->getLexicalDeclContext() && - D->getFirstDecl() == D->getMostRecentDecl() && - !D->isInvalidDecl() && - !D->hasAttrs() && - !D->isTopLevelDeclInObjCContainer() && + D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && + !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() && D->getDeclName().getNameKind() == DeclarationName::Identifier && - !D->hasExtInfo() && - !D->hasInheritedPrototype() && + !D->hasExtInfo() && !D->hasInheritedPrototype() && D->hasWrittenPrototype()) AbbrevToUse = Writer.getDeclBSCMethodAbbrev(); @@ -2284,11 +2281,11 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); DeclCXXMethodAbbrev = Stream.EmitAbbrev(std::move(Abv)); - // Abbreviation for DECL_BSC_METHOD + // Abbreviation for DECL_BSC_METHOD Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_BSC_METHOD)); // RedeclarableDecl - Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl + Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext @@ -2303,38 +2300,38 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Identifier - Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Identifier + Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber // ValueDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DeclaratorDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart - Abv->Add(BitCodeAbbrevOp(0)); // HasExtInfo - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart + Abv->Add(BitCodeAbbrevOp(0)); // HasExtInfo + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType // FunctionDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // StorageClass - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Inline - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InlineSpecified - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // VirtualAsWritten - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Pure - Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedProto - Abv->Add(BitCodeAbbrevOp(1)); // HasWrittenProto - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Deleted - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Trivial - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // TrivialForCall - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Defaulted - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitlyDefaulted - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ImplicitReturnZero - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constexpr - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // UsesSEHTry - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // SkippedBody - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // MultiVersion - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // StorageClass + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Inline + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InlineSpecified + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // VirtualAsWritten + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Pure + Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedProto + Abv->Add(BitCodeAbbrevOp(1)); // HasWrittenProto + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Deleted + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Trivial + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // TrivialForCall + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Defaulted + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitlyDefaulted + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ImplicitReturnZero + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constexpr + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // UsesSEHTry + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // SkippedBody + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // MultiVersion + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind // This Array slurps the rest of the record. Fortunately we want to encode // (nearly) all the remaining (variable number of) fields in the same way. // -- Gitee From 41775f97b7ed938ddc6ac409bac0cbb39cf5b1f4 Mon Sep 17 00:00:00 2001 From: Healing Date: Sat, 25 Feb 2023 03:49:52 +0000 Subject: [PATCH 4/8] !33 [BSC] bugfix for nullptr problem * [BSC] bugfix for nullptr problem --- clang/include/clang/AST/Decl.h | 2 +- clang/include/clang/AST/DeclCXX.h | 6 ++--- clang/include/clang/Sema/DeclSpec.h | 2 +- clang/include/clang/Sema/Sema.h | 2 +- clang/lib/AST/Decl.cpp | 2 +- clang/lib/Parse/ParseDecl.cpp | 10 ++++---- clang/lib/Sema/SemaDecl.cpp | 23 +++++++++++-------- .../BuiltInType/int_this_param_check.cbs | 4 ++++ .../BSC/Method/Enum/enum_this_param_check.cbs | 9 ++++++++ .../Method/Struct/struct_this_param_check.cbs | 7 ++++++ .../Method/Union/union_this_param_check.cbs | 11 +++++++++ 11 files changed, 56 insertions(+), 22 deletions(-) create mode 100644 clang/test/BSC/Method/BuiltInType/int_this_param_check.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_this_param_check.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_this_param_check.cbs create mode 100644 clang/test/BSC/Method/Union/union_this_param_check.cbs diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 1e54e91736a3..254e050b7777 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1645,7 +1645,7 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; - bool isThisParam = false; + bool IsThisParam = false; void setObjCMethodScopeInfo(unsigned parameterIndex) { ParmVarDeclBits.IsObjCMethodParam = true; diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 499320e554df..58ba43559e0e 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1952,8 +1952,8 @@ public: SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr); static BSCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); - bool getHasThisParam() const { return hasThisParam; } - void setHasThisParam(bool hasThisParam) { this->hasThisParam = hasThisParam; } + bool getHasThisParam() const { return HasThisParam; } + void setHasThisParam(bool HasThisParam) { this->HasThisParam = HasThisParam; } QualType getExtendedType() const { return ExtendedType; } void setExtendedType(QualType ExtendedType) { this->ExtendedType = ExtendedType; @@ -1965,7 +1965,7 @@ public: private: QualType ExtendedType; - bool hasThisParam = false; + bool HasThisParam = false; }; /// Represents a static or instance method of a struct/union/class. diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index e797da753ad7..f57c94ff35a3 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1928,7 +1928,7 @@ public: clear(); } // Used to mark parameters that include 'this'. - bool hasThisParam = false; + bool HasThisParam = false; /// getDeclSpec - Return the declaration-specifier that this declarator was /// declared with. const DeclSpec &getDeclSpec() const { return DS; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 5809edddd755..7d3b1be8bbc2 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2676,7 +2676,7 @@ public: bool IsDefinition); void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D); Decl *ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize = 0, - const Type *typePtr = nullptr); + const Type *TypePtr = nullptr); ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 9c4b8959111f..80b9be706ac4 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3342,7 +3342,7 @@ void FunctionDecl::setParams(ASTContext &C, unsigned FunctionDecl::getMinRequiredArguments() const { if (getASTContext().getLangOpts().BSC) { int num = getNumParams(); - if (num > 0 && parameters()[0] && parameters()[0]->isThisParam) { + if (num > 0 && parameters()[0] && parameters()[0]->IsThisParam) { num--; } return num; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 22be56c90274..ac03c25ee8dd 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1978,7 +1978,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, if (!D.getExtendedType().isNull()) { if (auto *MD = dyn_cast(TheDecl)) { MD->setExtendedType(D.getExtendedType()); - MD->setHasThisParam(D.hasThisParam); + MD->setHasThisParam(D.HasThisParam); } } return Actions.ConvertDeclToDeclGroup(TheDecl); @@ -2049,7 +2049,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, D.complete(FirstDecl); if (FirstDecl) { if (auto FD = dyn_cast(FirstDecl)) - FD->setHasThisParam(D.hasThisParam); + FD->setHasThisParam(D.HasThisParam); DeclsInGroup.push_back(FirstDecl); } @@ -6538,9 +6538,9 @@ void Parser::ParseFunctionDeclarator(Declarator &D, if (Tok.isNot(tok::r_paren)) { const Type *typePtr = nullptr; if (!D.getExtendedType().isNull()) { - typePtr = D.getExtendedType().getTypePtr(); + typePtr = D.getExtendedType().getTypePtrOrNull(); if (typePtr) - typePtr = typePtr->getCanonicalTypeUnqualified().getTypePtr(); + typePtr = typePtr->getCanonicalTypeUnqualified().getTypePtrOrNull(); } ParseParameterDeclarationClause(D.getContext(), FirstArgAttrs, ParamInfo, EllipsisLoc, typePtr); @@ -6551,7 +6551,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, ParmVarDecl *PD = dyn_cast_or_null(ParamInfo.data()[0].Param); if (PD && D.getBSCScopeSpec()) - D.hasThisParam = PD->isThisParam; + D.HasThisParam = PD->IsThisParam; } HasProto = ParamInfo.size() || getLangOpts().CPlusPlus || getLangOpts().OpenCL; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 1f46f0c784df..718ef43f7cd3 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13569,7 +13569,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) { + const Type *TypePtr) { const DeclSpec &DS = D.getDeclSpec(); // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. @@ -13614,18 +13614,21 @@ 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; - if (typePtr != nullptr && DeclarationName(II).getAsString() == "this") { + bool IsThisParam = false; + if (TypePtr != nullptr && DeclarationName(II).getAsString() == "this") { if (ParamSize == 0) { - auto thisTypePtr = parmDeclType.getTypePtr() - ->getPointeeType() - ->getCanonicalTypeUnqualified() - .getTypePtr(); - if (typePtr == nullptr || typePtr != thisTypePtr) { + auto ThisTypePtr = parmDeclType.getTypePtrOrNull(); + if (ThisTypePtr) { + ThisTypePtr = ThisTypePtr->getPointeeType().getTypePtrOrNull(); + if (ThisTypePtr) + ThisTypePtr = + ThisTypePtr->getCanonicalTypeUnqualified().getTypePtrOrNull(); + } + if (TypePtr != ThisTypePtr) { Diag(D.getBeginLoc(), diag::err_type_unsupported) << parmDeclType.getAsString(); } - isThisParam = true; + IsThisParam = true; } else { Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name) << GetNameForDeclarator(D).getName(); @@ -13661,7 +13664,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize, ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(), D.getBeginLoc(), D.getIdentifierLoc(), II, parmDeclType, TInfo, SC); - New->isThisParam = isThisParam; + New->IsThisParam = IsThisParam; if (D.isInvalidType()) New->setInvalidDecl(); diff --git a/clang/test/BSC/Method/BuiltInType/int_this_param_check.cbs b/clang/test/BSC/Method/BuiltInType/int_this_param_check.cbs new file mode 100644 index 000000000000..09fb8971031a --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_this_param_check.cbs @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -verify %s + +void int::increase(int this) { // expected-error {{int is not supported on this target}} +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_this_param_check.cbs b/clang/test/BSC/Method/Enum/enum_this_param_check.cbs new file mode 100644 index 000000000000..2c68b3fa2813 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_this_param_check.cbs @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int enum E::getA(enum E this); // expected-error {{enum E is not supported on this target}} + diff --git a/clang/test/BSC/Method/Struct/struct_this_param_check.cbs b/clang/test/BSC/Method/Struct/struct_this_param_check.cbs new file mode 100644 index 000000000000..240cca115de7 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_this_param_check.cbs @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { +}; +int struct Foo::getA(struct Foo this) { // expected-error {{struct Foo is not supported on this target}} + return 1; +} diff --git a/clang/test/BSC/Method/Union/union_this_param_check.cbs b/clang/test/BSC/Method/Union/union_this_param_check.cbs new file mode 100644 index 000000000000..a1a88c796d02 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_this_param_check.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(union SimpleUnion this) { // expected-error {{union SimpleUnion is not supported on this target}} + return 1; +} \ No newline at end of file -- Gitee From b94a3ebad45d8f648065b952b2d6ffa335de6aef Mon Sep 17 00:00:00 2001 From: MilMou Date: Mon, 27 Feb 2023 01:45:13 +0000 Subject: [PATCH 5/8] !32 [BSC] New parse logic for BSCMethod * [BSC] deleted an unused value * [BSC] changed function FindUntil * [BSC] New parse logic for BSCMethod --- clang/include/clang/Parse/Parser.h | 5 ++++- clang/lib/Parse/ParseDecl.cpp | 26 ++++++++++++-------------- clang/lib/Parse/Parser.cpp | 19 +++++++++++++++++++ clang/test/BSC/Method/definition_1.cbs | 7 +++++++ clang/test/BSC/Method/definition_2.cbs | 11 +++-------- clang/test/BSC/Method/definition_3.cbs | 11 +++-------- clang/test/BSC/Method/definition_4.cbs | 11 +++-------- 7 files changed, 51 insertions(+), 39 deletions(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index eb4a0488341d..bcc93854e543 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1010,6 +1010,9 @@ private: } }; + /// Judge whether there is a \param FindToken before StopTokens. + bool FindUntil(tok::TokenKind FindToken); + /// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the /// input. If so, it is consumed and false is returned. /// @@ -2356,7 +2359,7 @@ private: const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none, DeclSpecContext DSC = DeclSpecContext::DSC_normal, - LateParsedAttrList *LateAttrs = nullptr, bool BSCMethodFlag = false); + LateParsedAttrList *LateAttrs = nullptr, bool BSCScopeSpecFlag = false); void ParseBSCScopeSpecifiers(DeclSpec &DS); bool DiagnoseMissingSemiAfterTagDefinition( DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext, diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index ac03c25ee8dd..cc7856ad6f17 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2965,10 +2965,10 @@ static void SetupFixedPointError(const LangOptions &LangOpts, } void Parser::ParseBSCScopeSpecifiers(DeclSpec &DS) { - bool BSCMethodFlag = true; + bool BSCScopeSpecFlag = true; ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, DeclSpecContext::DSC_normal, nullptr, - BSCMethodFlag); + BSCScopeSpecFlag); } /// ParseDeclarationSpecifiers @@ -3003,7 +3003,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext, LateParsedAttrList *LateAttrs, - bool BSCMethodFlag) { + bool BSCScopeSpecFlag) { + bool BSCMethodFlag = false; + if (getLangOpts().BSC && !BSCScopeSpecFlag) + BSCMethodFlag = FindUntil(tok::coloncolon); if (DS.getSourceRange().isInvalid()) { // Start the range at the current token but make the end of the range // invalid. This will make the entire range invalid unless we successfully @@ -3019,15 +3022,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // We use Sema's policy to get bool macros right. PrintingPolicy Policy = Actions.getPrintingPolicy(); while (1) { - if (getLangOpts().BSC && DS.hasTypeSpecifier() && - ((BSCMethodFlag && Tok.is(tok::coloncolon) && - NextToken().is(tok::identifier)) || - (NextToken().is(tok::coloncolon) || - GetLookAheadToken(2).is(tok::coloncolon)))) { - ProhibitAttributes(attrs); - DS.Finish(Actions, Policy); - return; - } bool isInvalid = false; bool isStorageClass = false; const char *PrevSpec = nullptr; @@ -3051,6 +3045,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, SourceLocation Loc = Tok.getLocation(); + if (BSCMethodFlag && DS.hasTypeSpecifier()) + goto DoneWithDeclSpec; + switch (Tok.getKind()) { default: DoneWithDeclSpec: @@ -3121,6 +3118,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::coloncolon: // ::foo::bar // C++ scope specifier. Annotate and loop, or bail out on error. + if (BSCScopeSpecFlag) + goto DoneWithDeclSpec; if (TryAnnotateCXXScopeToken(EnteringContext)) { if (!DS.hasTypeSpecifier()) DS.SetTypeSpecError(); @@ -5695,8 +5694,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, D.setExtension(); // BSC - if (getLangOpts().BSC && (NextToken().is(tok::coloncolon) || - GetLookAheadToken(2).is(tok::coloncolon))) { + if (getLangOpts().BSC && FindUntil(tok::coloncolon)) { BSCScopeSpec BSS(*this); ParseBSCScopeSpecifiers(BSS); TryConsumeToken(tok::coloncolon); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 2a42f058b8ec..815d078f0c79 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -107,6 +107,25 @@ static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) { } } +bool Parser::FindUntil(tok::TokenKind FindToken) { + std::vector StopTokens {tok::l_brace, tok::semi, tok::eof, + tok::equal}; + int LookStep = 0; + tok::TokenKind KindToMatch; + + while (1) { + LookStep ++; + KindToMatch = GetLookAheadToken(LookStep).getKind(); + if (llvm::any_of(StopTokens, [KindToMatch](tok::TokenKind &Toke) { + return Toke == KindToMatch; + })) + return false; + if (FindToken == KindToMatch) { + return true; + } + } +} + bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, StringRef Msg) { if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) { diff --git a/clang/test/BSC/Method/definition_1.cbs b/clang/test/BSC/Method/definition_1.cbs index 0677d7e95cdc..5a837692ec03 100644 --- a/clang/test/BSC/Method/definition_1.cbs +++ b/clang/test/BSC/Method/definition_1.cbs @@ -1,3 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + struct Foo1 { int a; }; @@ -50,6 +53,10 @@ int short::getA0() { return 0; } +unsigned long int::getAa() { + return 0; +} + int main() { return 0; } diff --git a/clang/test/BSC/Method/definition_2.cbs b/clang/test/BSC/Method/definition_2.cbs index c199139b9f72..93ad7fdba34a 100644 --- a/clang/test/BSC/Method/definition_2.cbs +++ b/clang/test/BSC/Method/definition_2.cbs @@ -1,14 +1,9 @@ -int struct Foo::getA() { +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int struct Foo::getA() { // expected-error {{variable has incomplete type 'struct Foo'}} return 0; } int main() { return 0; } - -/* -definition_2.cbs:1:5: error: variable has incomplete type 'struct Foo' -int struct Foo::getA() { - ^ -1 error generated. -*/ diff --git a/clang/test/BSC/Method/definition_3.cbs b/clang/test/BSC/Method/definition_3.cbs index 3494c223d16c..13bd298fce86 100644 --- a/clang/test/BSC/Method/definition_3.cbs +++ b/clang/test/BSC/Method/definition_3.cbs @@ -1,16 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + struct Foo; -int struct Foo::getA() { +int struct Foo::getA() { // expected-error {{variable has incomplete type 'struct Foo'}} return 0; } int main() { return 0; } - -/* -definition_3.cbs:3:5: error: variable has incomplete type 'struct Foo' -int struct Foo::getA() { - ^ -1 error generated. -*/ diff --git a/clang/test/BSC/Method/definition_4.cbs b/clang/test/BSC/Method/definition_4.cbs index ea9aeedc9fe5..47417394667f 100644 --- a/clang/test/BSC/Method/definition_4.cbs +++ b/clang/test/BSC/Method/definition_4.cbs @@ -1,14 +1,9 @@ -int void::getA() { +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int void::getA() { // expected-error {{variable has incomplete type 'void'}} return 0; } int main() { return 0; } - -/* -definition_4.cbs:1:5: error: variable has incomplete type 'void' -int void::getA() { - ^ -1 error generated. -*/ -- Gitee From c40ba3da515aa9436a48f508da976d7bc4763dd8 Mon Sep 17 00:00:00 2001 From: Healing Date: Wed, 1 Mar 2023 09:10:15 +0000 Subject: [PATCH 6/8] !34 [BSC] check funtion call * [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 cc7856ad6f17..bbda96757d33 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); } @@ -6548,7 +6550,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 From 278770c9920f2c32bb109e6e297a95bd92244e8c Mon Sep 17 00:00:00 2001 From: Healing Date: Thu, 2 Mar 2023 12:44:29 +0000 Subject: [PATCH 7/8] !21 [BSC] support function pointer * fix review suggestions * [BSC] support function pointer --- clang/include/clang/AST/Expr.h | 1 + clang/include/clang/Parse/Parser.h | 4 +- clang/include/clang/Sema/Sema.h | 8 ++- clang/lib/Parse/ParseDecl.cpp | 2 +- clang/lib/Parse/ParseExpr.cpp | 57 ++++++++++++++++--- clang/lib/Parse/ParseStmt.cpp | 4 +- clang/lib/Sema/SemaDecl.cpp | 5 +- clang/lib/Sema/SemaExpr.cpp | 21 ++++--- clang/lib/Sema/SemaLookup.cpp | 11 +++- clang/lib/Sema/SemaType.cpp | 6 +- .../BuiltInType/int_conflict_param_type.cbs | 6 ++ .../BuiltInType/int_conflict_return_type.cbs | 6 ++ .../int_function_pointer_undeclared.cbs | 11 ++++ .../int_instance_function_call.cbs | 11 ++++ .../int_instance_function_pointer.cbs | 15 +++++ .../int_instance_function_with_typedef.cbs | 16 ++++++ .../BuiltInType/int_static_function_call.cbs | 12 ++++ .../Method/Enum/enum_conflict_param_type.cbs | 11 ++++ .../Method/Enum/enum_conflict_return_type.cbs | 11 ++++ .../Enum/enum_function_pointer_undeclared.cbs | 16 ++++++ .../Enum/enum_instance_function_call.cbs | 17 ++++++ .../Enum/enum_instance_function_pointer.cbs | 20 +++++++ .../enum_instance_function_with_typedef.cbs | 19 +++++++ .../Struct/struct_conflict_no_param_1.cbs | 10 ++++ .../Struct/struct_conflict_no_param_2.cbs | 8 +++ .../Struct/struct_conflict_param_type.cbs | 10 ++++ .../Struct/struct_conflict_return_type.cbs | 10 ++++ .../Struct/struct_function_undeclared.cbs | 15 +++++ .../Struct/struct_instance_function.cbs} | 14 ++--- .../Struct/struct_instance_function_call.cbs | 16 ++++++ .../struct_instance_function_declaration.cbs | 18 ++++++ ...ct_instance_function_multi_declaration.cbs | 19 +++++++ .../struct_instance_function_not_found.cbs | 16 ++++++ .../struct_instance_function_pointer.cbs | 20 +++++++ .../struct_instance_function_redefinition.cbs | 19 +++++++ ...struct_instance_function_with_typedef.cbs} | 20 +++---- .../Struct/struct_static_function_call.cbs | 19 +++++++ .../Union/union_conflict_param_type.cbs | 12 ++++ .../Union/union_conflict_return_type.cbs | 12 ++++ .../union_function_pointer_undeclared.cbs | 17 ++++++ .../Union/union_instance_function_call.cbs | 18 ++++++ .../Union/union_instance_function_pointer.cbs | 21 +++++++ .../union_instance_function_with_typedef.cbs | 20 +++++++ .../BSC/ParamCheck/this_not_first_param.cbs | 37 ++++++++++++ .../ParamCheck/this_param_type_no_match.cbs | 40 +++++++++++++ .../BSC/ParamCheck/this_param_with_const.cbs | 50 ++++++++++++++++ .../ParamCheck/this_param_with_volatile.cbs | 49 ++++++++++++++++ clang/test/BSC/pending/CallBeforeDefine.cbs | 17 ------ clang/test/BSC/pending/OverloadFunc.cbs | 24 -------- clang/test/BSC/pending/StaticMemberFunc.cbs | 20 ------- clang/test/BSC/pending/ThisParamCheck1.cbs | 17 ------ clang/test/BSC/pending/ThisParamCheck2.cbs | 21 ------- 52 files changed, 734 insertions(+), 145 deletions(-) create mode 100644 clang/test/BSC/Method/BuiltInType/int_conflict_param_type.cbs create mode 100644 clang/test/BSC/Method/BuiltInType/int_conflict_return_type.cbs create mode 100644 clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs create mode 100644 clang/test/BSC/Method/BuiltInType/int_instance_function_call.cbs create mode 100644 clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs create mode 100644 clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs create mode 100644 clang/test/BSC/Method/BuiltInType/int_static_function_call.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_conflict_param_type.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_conflict_return_type.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_instance_function_call.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_conflict_no_param_1.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_conflict_no_param_2.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_conflict_param_type.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_conflict_return_type.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_function_undeclared.cbs rename clang/test/BSC/{pending/InstanceMemberFunc.cbs => Method/Struct/struct_instance_function.cbs} (39%) create mode 100644 clang/test/BSC/Method/Struct/struct_instance_function_call.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_instance_function_not_found.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_instance_function_redefinition.cbs rename clang/test/BSC/{pending/Typedef.cbs => Method/Struct/struct_instance_function_with_typedef.cbs} (45%) create mode 100644 clang/test/BSC/Method/Struct/struct_static_function_call.cbs create mode 100644 clang/test/BSC/Method/Union/union_conflict_param_type.cbs create mode 100644 clang/test/BSC/Method/Union/union_conflict_return_type.cbs create mode 100644 clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs create mode 100644 clang/test/BSC/Method/Union/union_instance_function_call.cbs create mode 100644 clang/test/BSC/Method/Union/union_instance_function_pointer.cbs create mode 100644 clang/test/BSC/Method/Union/union_instance_function_with_typedef.cbs create mode 100644 clang/test/BSC/ParamCheck/this_not_first_param.cbs create mode 100644 clang/test/BSC/ParamCheck/this_param_type_no_match.cbs create mode 100644 clang/test/BSC/ParamCheck/this_param_with_const.cbs create mode 100644 clang/test/BSC/ParamCheck/this_param_with_volatile.cbs delete mode 100644 clang/test/BSC/pending/CallBeforeDefine.cbs delete mode 100644 clang/test/BSC/pending/OverloadFunc.cbs delete mode 100644 clang/test/BSC/pending/StaticMemberFunc.cbs delete mode 100644 clang/test/BSC/pending/ThisParamCheck1.cbs delete mode 100644 clang/test/BSC/pending/ThisParamCheck2.cbs diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index a44d06967431..b19f98326eeb 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -138,6 +138,7 @@ protected: friend class ASTStmtReader; // Sets dependence dircetly. public: + bool HasBSCScopeSpce = false; QualType getType() const { return TR; } void setType(QualType t) { // In C++, the type of an expression is always adjusted so that it diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index bcc93854e543..6f53fea395be 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1792,7 +1792,9 @@ private: bool &NotCastExpr, TypeCastState isTypeCast, bool isVectorLiteral = false, - bool *NotPrimaryExpression = nullptr); + bool *NotPrimaryExpression = nullptr, + QualType T = QualType(), + bool HasBSCScopeSpce = false); ExprResult ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand = false, TypeCastState isTypeCast = NotTypeCast, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7d3b1be8bbc2..b0c085d98044 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2671,7 +2671,8 @@ public: QualType NewT, QualType OldT); void CheckMain(FunctionDecl *FD, const DeclSpec &D); void CheckMSVCRTEntryPoint(FunctionDecl *FD); - void ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc); + QualType ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc, + bool AddToContextMap); Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition); void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D); @@ -4072,7 +4073,7 @@ public: CXXScopeSpec &SS); bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, bool AllowBuiltinCreation = false, - bool EnteringContext = false); + bool EnteringContext = false, QualType T = QualType()); ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc, RedeclarationKind Redecl = NotForRedeclaration); @@ -5072,7 +5073,8 @@ public: Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand, CorrectionCandidateCallback *CCC = nullptr, - bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr); + bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr, + QualType T = QualType()); void DecomposeUnqualifiedId(const UnqualifiedId &Id, TemplateArgumentListInfo &Buffer, diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index bbda96757d33..f475e675c455 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5702,7 +5702,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, TryConsumeToken(tok::coloncolon); D.setBSCScopeSpec(&BSS); - Actions.ConvertBSCScopeSpecToType(D, BSS.getBeginLoc()); + Actions.ConvertBSCScopeSpecToType(D, BSS.getBeginLoc(), true); (this->*DirectDeclParser)(D); return; } diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 6acf76d713fd..6fb1a7dba79a 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -909,12 +909,11 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback { /// '__is_rvalue_expr' /// \endverbatim /// -ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, - bool isAddressOfOperand, - bool &NotCastExpr, - TypeCastState isTypeCast, - bool isVectorLiteral, - bool *NotPrimaryExpression) { +ExprResult +Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, + bool &NotCastExpr, TypeCastState isTypeCast, + bool isVectorLiteral, bool *NotPrimaryExpression, + QualType T, bool HasBSCScopeSpce) { ExprResult Res; tok::TokenKind SavedKind = Tok.getKind(); auto SavedType = PreferredType; @@ -1036,10 +1035,38 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super)); return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast, isVectorLiteral, NotPrimaryExpression); - + case tok::kw_union: + case tok::kw_enum: + case tok::kw_struct: + if (getLangOpts().BSC && FindUntil(tok::coloncolon)) { + ParsingDeclSpec BSS(*this); + ParseBSCScopeSpecifiers(BSS); + ParsingDeclarator D(*this, BSS, DeclaratorContext::File); + D.setBSCScopeSpec(&BSS); + QualType T = Actions.ConvertBSCScopeSpecToType( + D, BSS.getBeginLoc(), false); // get scope type for BSC + HasBSCScopeSpce = TryConsumeToken(tok::coloncolon); + return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, + isTypeCast, isVectorLiteral, + NotPrimaryExpression, T, HasBSCScopeSpce); + } + // Fall through; this isn't a message send. + LLVM_FALLTHROUGH; case tok::identifier: { // primary-expression: identifier // unqualified-id: identifier // constant: enumeration-constant + if (getLangOpts().BSC && FindUntil(tok::coloncolon)) { + ParsingDeclSpec BSS(*this); + ParseBSCScopeSpecifiers(BSS); + ParsingDeclarator D(*this, BSS, DeclaratorContext::File); + D.setBSCScopeSpec(&BSS); + QualType T = Actions.ConvertBSCScopeSpecToType( + D, BSS.getBeginLoc(), false); // get scope type for BSC + HasBSCScopeSpce = TryConsumeToken(tok::coloncolon); + return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, + isTypeCast, isVectorLiteral, + NotPrimaryExpression, T, HasBSCScopeSpce); + } // Turn a potentially qualified name into a annot_typename or // annot_cxxscope if it would be valid. This handles things like x::y, etc. if (getLangOpts().CPlusPlus) { @@ -1251,7 +1278,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren), isAddressOfOperand, &Validator, /*IsInlineAsmIdentifier=*/false, - Tok.is(tok::r_paren) ? nullptr : &Replacement); + Tok.is(tok::r_paren) ? nullptr : &Replacement, T); if (!Res.isInvalid() && Res.isUnset()) { UnconsumeToken(Replacement); return ParseCastExpression(ParseKind, isAddressOfOperand, @@ -1525,6 +1552,18 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t: #include "clang/Basic/OpenCLImageTypes.def" { + if (getLangOpts().BSC && FindUntil(tok::coloncolon)) { + ParsingDeclSpec BSS(*this); + ParseBSCScopeSpecifiers(BSS); + ParsingDeclarator D(*this, BSS, DeclaratorContext::File); + D.setBSCScopeSpec(&BSS); + QualType T = Actions.ConvertBSCScopeSpecToType( + D, BSS.getBeginLoc(), false); // get scope type for BSC + HasBSCScopeSpce = TryConsumeToken(tok::coloncolon); + return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, + isTypeCast, isVectorLiteral, + NotPrimaryExpression, T, HasBSCScopeSpce); + } if (!getLangOpts().CPlusPlus) { Diag(Tok, diag::err_expected_expression); return ExprError(); @@ -1806,6 +1845,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, // These can be followed by postfix-expr pieces. PreferredType = SavedType; + if (Res.get()) + Res.get()->HasBSCScopeSpce = HasBSCScopeSpce; Res = ParsePostfixExpressionSuffix(Res); if (getLangOpts().OpenCL) if (Expr *PostfixExpr = Res.get()) { diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 35d3b4b718db..0170003db76e 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -211,7 +211,9 @@ Default: if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt || (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) != ParsedStmtContext()) && - (GNUAttributeLoc.isValid() || isDeclarationStatement())) { + (GNUAttributeLoc.isValid() || + (isDeclarationStatement() && + !(getLangOpts().BSC && FindUntil(tok::coloncolon))))) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy Decl; if (GNUAttributeLoc.isValid()) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 718ef43f7cd3..dc80bde5f638 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3680,7 +3680,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, // C: Function types need to be compatible, not identical. This handles // duplicate function decls like "void f(int); void f(enum X);" properly. - if (!getLangOpts().CPlusPlus && + if (!getLangOpts().CPlusPlus && ! getLangOpts().BSC && Context.typesAreCompatible(OldQType, NewQType)) { const FunctionType *OldFuncType = OldQType->getAs(); const FunctionType *NewFuncType = NewQType->getAs(); @@ -13615,7 +13615,8 @@ 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; - if (TypePtr != nullptr && DeclarationName(II).getAsString() == "this") { + // if TypePtr is nullptr, it is not a BSCMethod + if (TypePtr && DeclarationName(II).getAsString() == "this") { if (ParamSize == 0) { auto ThisTypePtr = parmDeclType.getTypePtrOrNull(); if (ThisTypePtr) { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index aea9cacdfa53..8843c1f8d082 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2422,7 +2422,8 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand, CorrectionCandidateCallback *CCC, - bool IsInlineAsmIdentifier, Token *KeywordReplacement) { + bool IsInlineAsmIdentifier, Token *KeywordReplacement, + QualType T) { assert(!(IsAddressOfOperand && HasTrailingLParen) && "cannot be direct & operand and have a trailing lparen"); if (SS.isInvalid()) @@ -2472,7 +2473,6 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, if (DependentID) return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, IsAddressOfOperand, TemplateArgs); - // Perform the required lookup. LookupResult R(*this, NameInfo, (Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam) @@ -2497,7 +2497,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, IsAddressOfOperand, TemplateArgs); } else { bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl(); - LookupParsedName(R, S, &SS, !IvarLookupFollowUp); + LookupParsedName(R, S, &SS, !IvarLookupFollowUp, false, T); // If the result might be in a dependent base class, this is a dependent // id-expression. @@ -2522,7 +2522,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // This could be an implicitly declared function reference (legal in C90, // extension in C99, forbidden in C++). - if (R.empty() && HasTrailingLParen && II && !getLangOpts().CPlusPlus) { + if (R.empty() && HasTrailingLParen && II && !getLangOpts().CPlusPlus && !getLangOpts().BSC) { NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S); if (D) R.addDecl(D); } @@ -3423,7 +3423,12 @@ ExprResult Sema::BuildDeclarationNameExpr( valueKind = VK_RValue; break; } - LLVM_FALLTHROUGH; + + // BSC methods are l-values if static, r-values if non-static. + if (cast(VD)->isStatic()) { + valueKind = VK_LValue; + } + break; case Decl::CXXMethod: // If we're referring to a method with an __unknown_anytype @@ -5780,8 +5785,8 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, : (IsExecConfig ? 3 /* kernel function (exec config) */ : 0 /* function */); bool isBSCInstanceFunc = false; - if (FDecl) { - BSCMethodDecl *MD = dyn_cast_or_null(FDecl); + if (FDecl && !Fn->HasBSCScopeSpce) { + BSCMethodDecl* MD = dyn_cast_or_null(FDecl); if (MD && MD->getHasThisParam()) { isBSCInstanceFunc = true; NumParams = NumParams - 1; @@ -6616,6 +6621,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, ArrayRef Args, SourceLocation RParenLoc, Expr *Config, bool IsExecConfig, ADLCallKind UsesADL) { + bool HasBSCScopeSpce = Fn->HasBSCScopeSpce; FunctionDecl *FDecl = dyn_cast_or_null(NDecl); unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0); @@ -6657,6 +6663,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (Result.isInvalid()) return ExprError(); Fn = Result.get(); + Fn->HasBSCScopeSpce = HasBSCScopeSpce; // Check for a valid function type, but only if it is not a builtin which // requires custom type checking. These will be handled by diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 2d8a65dcaae6..f9b5e7dc2a6c 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -2405,7 +2405,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, /// /// @returns True if any decls were found (but possibly ambiguous) bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, - bool AllowBuiltinCreation, bool EnteringContext) { + bool AllowBuiltinCreation, bool EnteringContext, + QualType T) { if (SS && SS->isInvalid()) { // When the scope specifier is invalid, don't even look for // anything. @@ -2435,6 +2436,14 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, return false; } + if (!T.isNull() && getLangOpts().BSC) { + DeclContext *DC = getASTContext().BSCDeclContextMap[T.getCanonicalType().getTypePtr()]; + if (DC) + return LookupQualifiedName(R, DC); + else + Diag(R.getNameLoc(), diag::err_undeclared_var_use) << R.getLookupName(); + } + // Perform unqualified name lookup starting in the given scope. return LookupName(R, S, AllowBuiltinCreation); } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 52b0fecf8551..75e8e350bd48 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1837,7 +1837,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state, return Result; } -void Sema::ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc) { +QualType Sema::ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc, + bool AddToContextMap) { TypeProcessingState state(*this, D); bool BSCMethodFlag = true; QualType T = ConvertDeclSpecToType(state, BSCMethodFlag); @@ -1845,7 +1846,7 @@ void Sema::ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc) { if (T->isIncompleteType(&Def)) { BoundTypeDiagnoser<> Diagnoser(diag::err_typecheck_decl_incomplete_type); Diagnoser.diagnose(*this, Loc, T); - } else { + } else if (AddToContextMap) { D.setExtendedType(T); const Type *BasedType = T.getCanonicalType().getTypePtr(); // build declcontext map @@ -1870,6 +1871,7 @@ void Sema::ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc) { } } } + return T; } static std::string getPrintableNameForEntity(DeclarationName Entity) { diff --git a/clang/test/BSC/Method/BuiltInType/int_conflict_param_type.cbs b/clang/test/BSC/Method/BuiltInType/int_conflict_param_type.cbs new file mode 100644 index 000000000000..af4bfb2c8ad0 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_conflict_param_type.cbs @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -verify %s + +void int::increase(int a); // expected-note {{previous declaration is here}} +void int::increase(int* this) { // expected-error {{conflicting types for 'increase'}} + *this = *this +1; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_conflict_return_type.cbs b/clang/test/BSC/Method/BuiltInType/int_conflict_return_type.cbs new file mode 100644 index 000000000000..2007a3dadd2f --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_conflict_return_type.cbs @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -verify %s + +double int::increase(int* this); // expected-note {{previous declaration is here}} +void int::increase(int* this) { // expected-error {{conflicting types for 'increase'}} + *this = *this +1; +} \ 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 new file mode 100644 index 000000000000..274e6134f102 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +int getA() { + 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'}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_call.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_call.cbs new file mode 100644 index 000000000000..ff822dbe784f --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_call.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/BuiltInType/int_instance_function_pointer.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs new file mode 100644 index 000000000000..5869645b7c24 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +void int::increase(int* this) { + *this = *this +1; +} + +int main() { + int foo = 1; + void (*fp1)(int *) = int::increase; + void (*fp2)(int *) = &int::increase; + fp1(&foo); + fp2(&foo); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs new file mode 100644 index 000000000000..6b5890a2b442 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +typedef int bscInt; + +void bscInt::increase_1(bscInt* this) { + *this = *this + 1; +} + +void int::increase_2(bscInt* this) { + *this = *this + 1; +} + +void int::increase_3(int* this) { + *this = *this + 1; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_static_function_call.cbs b/clang/test/BSC/Method/BuiltInType/int_static_function_call.cbs new file mode 100644 index 000000000000..9c747a9ed771 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_static_function_call.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +int int::getA() { + return 2; +} + +int main() { + int::getA(); + int a = int::getA(); + return a - 2; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_conflict_param_type.cbs b/clang/test/BSC/Method/Enum/enum_conflict_param_type.cbs new file mode 100644 index 000000000000..6155a971d31a --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_conflict_param_type.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int enum E::getA(int a); // expected-note {{previous declaration is here}} +int enum E::getA(enum E* this) { // expected-error {{conflicting types for 'getA'}} + return X4; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_conflict_return_type.cbs b/clang/test/BSC/Method/Enum/enum_conflict_return_type.cbs new file mode 100644 index 000000000000..b14149765fc9 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_conflict_return_type.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +double enum E::getA(enum E* this); // expected-note {{previous declaration is here}} +int enum E::getA(enum E* this) { // expected-error {{conflicting types for 'getA'}} + return X4; +} \ 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 new file mode 100644 index 000000000000..595e5db3448a --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int getA() { + 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'}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_call.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_call.cbs new file mode 100644 index 000000000000..446adccb1d04 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_instance_function_call.cbs @@ -0,0 +1,17 @@ +// 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 e= X3; + e.getA(&e); // 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_instance_function_pointer.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs new file mode 100644 index 000000000000..2681e682d0d6 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +enum E { + X3, + X4 +}; + +int enum E::getA(enum E* this) { + return X4; +} + +int main() { + enum E foo = X3; + int (*fp1)(enum E *) = enum E::getA; + int (*fp2)(enum E *) = &enum E::getA; + fp1(&foo); + fp2(&foo); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs new file mode 100644 index 000000000000..2042dba0cef0 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +typedef enum E { + X3, + X4 +}E; + +int E::getX4_1(E* this) { + return X4; +} + +int E::getX4_2(enum E* this) { + return X4; +} + +int enum E::getX4_3(enum E* this) { + return X4; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_conflict_no_param_1.cbs b/clang/test/BSC/Method/Struct/struct_conflict_no_param_1.cbs new file mode 100644 index 000000000000..9809668a6c97 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_conflict_no_param_1.cbs @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(); // expected-note {{previous declaration is here}} +int struct Foo::getA(struct Foo* this) { // expected-error {{conflicting types for 'getA'}} + return this->a; +} diff --git a/clang/test/BSC/Method/Struct/struct_conflict_no_param_2.cbs b/clang/test/BSC/Method/Struct/struct_conflict_no_param_2.cbs new file mode 100644 index 000000000000..9e97ea8f6845 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_conflict_no_param_2.cbs @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(); // expected-note {{previous declaration is here}} +int struct Foo::getA(struct Foo* this); // expected-error {{conflicting types for 'getA'}} diff --git a/clang/test/BSC/Method/Struct/struct_conflict_param_type.cbs b/clang/test/BSC/Method/Struct/struct_conflict_param_type.cbs new file mode 100644 index 000000000000..0ee0da65372b --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_conflict_param_type.cbs @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(int a); // expected-note {{previous declaration is here}} +int struct Foo::getA(struct Foo* this) { // expected-error {{conflicting types for 'getA'}} + return this->a; +} diff --git a/clang/test/BSC/Method/Struct/struct_conflict_return_type.cbs b/clang/test/BSC/Method/Struct/struct_conflict_return_type.cbs new file mode 100644 index 000000000000..b294fecd1800 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_conflict_return_type.cbs @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +double struct Foo::getA(struct Foo* this); // expected-note {{previous declaration is here}} +int struct Foo::getA(struct Foo* this) { // expected-error {{conflicting types for 'getA'}} + return this->a; +} diff --git a/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs b/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs new file mode 100644 index 000000000000..5849ca25dfcc --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int getA() { + 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'}} + return 0; +} diff --git a/clang/test/BSC/pending/InstanceMemberFunc.cbs b/clang/test/BSC/Method/Struct/struct_instance_function.cbs similarity index 39% rename from clang/test/BSC/pending/InstanceMemberFunc.cbs rename to clang/test/BSC/Method/Struct/struct_instance_function.cbs index 0cdd03d421b1..416f7e75c499 100644 --- a/clang/test/BSC/pending/InstanceMemberFunc.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_function.cbs @@ -1,17 +1,17 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -verify %s // expected-no-diagnostics -typedef struct Foo{ + +struct Foo { int a; -}Foo; +}; -int Foo::getA(struct Foo* this) { +int struct Foo::getA(struct Foo* this) { return this->a; } + int main() { - Foo foo; - foo.a = 42; + struct Foo foo = {.a = 1}; foo.getA(); - Foo::getA(&foo); return 0; } \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_call.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_call.cbs new file mode 100644 index 000000000000..0e6a528eebfe --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_call.cbs @@ -0,0 +1,16 @@ +// 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 = {.a = 1}; + 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_instance_function_declaration.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs new file mode 100644 index 000000000000..e6c4c2fcd2f3 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this); + +int main() { + struct Foo foo = {.a = 1}; + foo.getA(); + return 0; +} + +int struct Foo::getA(struct Foo* this) { + return this->a; +} diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs new file mode 100644 index 000000000000..ff1fdddc42e4 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this); +int struct Foo::getA(struct Foo* this); + +int main() { + struct Foo foo = {.a = 1}; + foo.getA(); + return 0; +} + +int struct Foo::getA(struct Foo* this) { + return this->a; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_not_found.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_not_found.cbs new file mode 100644 index 000000000000..e7665e9cb107 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_not_found.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this) { + return this->a; +} + + +int main() { + struct Foo foo = {.a = 1}; + foo.getB(); // expected-error {{no member named 'getB' in 'struct Foo'}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs new file mode 100644 index 000000000000..ebd1a859d149 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this) { + return this->a; +} + + +int main() { + struct Foo foo = {.a = 1}; + int (*fp1)(struct Foo *) = struct Foo::getA; + int (*fp2)(struct Foo *) = &struct Foo::getA; + fp1(&foo); + fp2(&foo); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_redefinition.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_redefinition.cbs new file mode 100644 index 000000000000..d8aa505bd885 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_redefinition.cbs @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this) { // expected-note {{previous definition is here}} + return this->a; +} + +int struct Foo::getA(struct Foo* this) { // expected-error {{redefinition of 'getA'}} + return this->a; +} + +int main() { + struct Foo foo = {.a = 1}; + foo.getA(); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/pending/Typedef.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_with_typedef.cbs similarity index 45% rename from clang/test/BSC/pending/Typedef.cbs rename to clang/test/BSC/Method/Struct/struct_instance_function_with_typedef.cbs index ee779a449bcb..a48f320d52ff 100644 --- a/clang/test/BSC/pending/Typedef.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_function_with_typedef.cbs @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -verify %s // expected-no-diagnostics -struct Foo { + +typedef struct Foo { int a; int b; -}; -typedef struct Foo Foo; +}Foo; int Foo::getB(Foo* this) { return this->b; @@ -14,12 +14,6 @@ int Foo::getAPlusB(struct Foo* this) { return this->a + this->b; } -int main() { - Foo foo; - foo.a = 42; - foo.b = 2023; - int b = foo.getB(); - int ab = foo.getAPlusB(); - return 0; -} - +int struct Foo::getA(struct Foo* this) { + return this->a; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_static_function_call.cbs b/clang/test/BSC/Method/Struct/struct_static_function_call.cbs new file mode 100644 index 000000000000..995c843391ff --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_static_function_call.cbs @@ -0,0 +1,19 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// expected-no-diagnostics + +struct Foo { + int a; +}; + +int struct Foo::getA() { + return 1; +} + + +int main() { + struct Foo foo = {.a = 1}; + struct Foo::getA(); + int a = struct Foo::getA(); + return a - 1; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_conflict_param_type.cbs b/clang/test/BSC/Method/Union/union_conflict_param_type.cbs new file mode 100644 index 000000000000..3950cd93c3b1 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_conflict_param_type.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(int a); // expected-note {{previous declaration is here}} +int union SimpleUnion::getA(union SimpleUnion * this) { // expected-error {{conflicting types for 'getA'}} + return this->ui; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_conflict_return_type.cbs b/clang/test/BSC/Method/Union/union_conflict_return_type.cbs new file mode 100644 index 000000000000..bad0123c1d9e --- /dev/null +++ b/clang/test/BSC/Method/Union/union_conflict_return_type.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +double union SimpleUnion::getA(union SimpleUnion * this); // expected-note {{previous declaration is here}} +int union SimpleUnion::getA(union SimpleUnion * this) { // expected-error {{conflicting types for 'getA'}} + return this->ui; +} \ 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 new file mode 100644 index 000000000000..8993ac904fb7 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int getA() { + 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'}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_instance_function_call.cbs b/clang/test/BSC/Method/Union/union_instance_function_call.cbs new file mode 100644 index 000000000000..e0bab4d1de38 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_instance_function_call.cbs @@ -0,0 +1,18 @@ +// 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 diff --git a/clang/test/BSC/Method/Union/union_instance_function_pointer.cbs b/clang/test/BSC/Method/Union/union_instance_function_pointer.cbs new file mode 100644 index 000000000000..3dc1847eb71a --- /dev/null +++ b/clang/test/BSC/Method/Union/union_instance_function_pointer.cbs @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(union SimpleUnion * this) { + return this->ui; +} + +int main() { + union SimpleUnion foo = {.ui = 1}; + int (*fp1)(union SimpleUnion *) = union SimpleUnion::getA; + int (*fp2)(union SimpleUnion *) = &union SimpleUnion::getA; + fp1(&foo); + fp2(&foo); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_instance_function_with_typedef.cbs b/clang/test/BSC/Method/Union/union_instance_function_with_typedef.cbs new file mode 100644 index 000000000000..153b409a1d00 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_instance_function_with_typedef.cbs @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +typedef union SimpleUnion { + float uf; + int ui; + char uc; +}SimpleUnion; + +int SimpleUnion::getui_1(SimpleUnion* this) { + return this->ui; +} + +int SimpleUnion::getui_2(union SimpleUnion* this) { + return this->ui; +} + +int union SimpleUnion::getui_3(union SimpleUnion* this) { + return this->ui; +} \ No newline at end of file diff --git a/clang/test/BSC/ParamCheck/this_not_first_param.cbs b/clang/test/BSC/ParamCheck/this_not_first_param.cbs new file mode 100644 index 000000000000..7fe4902bed43 --- /dev/null +++ b/clang/test/BSC/ParamCheck/this_not_first_param.cbs @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -verify %s + +// struct +struct Foo { + int a; +}; + +int struct Foo::getA(int b, struct Foo* this) { // expected-error {{'this' cannot be the name of a parameter}} + return this->a; +} + +// enum +enum E { + X3, + X4 +}; + +int enum E::getA(int b, enum E* this) { // expected-error {{'this' cannot be the name of a parameter}} + return X4; +} + +// union +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(int b, union SimpleUnion* this) { // expected-error {{'this' cannot be the name of a parameter}} + return this->ui; +} + +// BuiltinType +void int::increase(int b, int* this) { // expected-error {{'this' cannot be the name of a parameter}} + *this = *this + b; +} + diff --git a/clang/test/BSC/ParamCheck/this_param_type_no_match.cbs b/clang/test/BSC/ParamCheck/this_param_type_no_match.cbs new file mode 100644 index 000000000000..bcb0222f9857 --- /dev/null +++ b/clang/test/BSC/ParamCheck/this_param_type_no_match.cbs @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -verify %s + +// struct +struct Foo { + int a; +}; + +struct Bar { + int a; +}; + +int struct Foo::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} + return this->a; +} + +// enum +enum E { + X3, + X4 +}; + +int enum E::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} + return this->a; +} + +// union +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} + return this->a; +} + +// BuiltinType +int int::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} + return this->a; +} \ No newline at end of file diff --git a/clang/test/BSC/ParamCheck/this_param_with_const.cbs b/clang/test/BSC/ParamCheck/this_param_with_const.cbs new file mode 100644 index 000000000000..a6c7aa7e29f1 --- /dev/null +++ b/clang/test/BSC/ParamCheck/this_param_with_const.cbs @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +// struct +struct Foo { + int a; +}; + +int struct Foo::getA(const struct Foo* this) { + return this->a; +} + +// enum +enum E { + X3, + X4 +}; + +int enum E::getA(const enum E* this) { + return X4; +} + +// union +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(const union SimpleUnion* this) { + return this->ui; +} + +// BuiltinType +int int::getA(const int* this) { + return *this; +} + +int main() { + struct Foo foo ={.a = 42}; + foo.getA(); + enum E e= X3; + e.getA(); + union SimpleUnion u = {.ui = 1}; + u.getA(); + int one = 1; + one.getA(); + return 0; +} + diff --git a/clang/test/BSC/ParamCheck/this_param_with_volatile.cbs b/clang/test/BSC/ParamCheck/this_param_with_volatile.cbs new file mode 100644 index 000000000000..2402e40ffdbe --- /dev/null +++ b/clang/test/BSC/ParamCheck/this_param_with_volatile.cbs @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +// struct +struct Foo { + int a; +}; + +int struct Foo::getA(volatile struct Foo* this) { + return this->a; +} + +// enum +enum E { + X3, + X4 +}; + +int enum E::getA(volatile enum E* this) { + return X4; +} + +// union +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(volatile union SimpleUnion* this) { + return this->ui; +} + +// BuiltinType +int int::getA(volatile int* this) { + return *this; +} + +int main() { + struct Foo foo ={.a = 42}; + foo.getA(); + enum E e= X3; + e.getA(); + union SimpleUnion u = {.ui = 1}; + u.getA(); + int one = 1; + one.getA(); + return 0; +} diff --git a/clang/test/BSC/pending/CallBeforeDefine.cbs b/clang/test/BSC/pending/CallBeforeDefine.cbs deleted file mode 100644 index c8e9187030a7..000000000000 --- a/clang/test/BSC/pending/CallBeforeDefine.cbs +++ /dev/null @@ -1,17 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics -typedef struct Foo { - int a; -}Foo; - -int Foo::getA(struct Foo* this); - -int main() { - struct Foo foo; - foo.a = 42; - return foo.getA(); -} - -int Foo::getA(struct Foo* this) { - return this->a; -} \ No newline at end of file diff --git a/clang/test/BSC/pending/OverloadFunc.cbs b/clang/test/BSC/pending/OverloadFunc.cbs deleted file mode 100644 index 442a57b87669..000000000000 --- a/clang/test/BSC/pending/OverloadFunc.cbs +++ /dev/null @@ -1,24 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -struct Foo { - int a; -}; -typedef struct Foo F; - -int F::f2(F* this) { -// expected-note@-1 {{previous definition is here}} -// expected-note@-2 {{passing argument to parameter 'this' here}} - return 1; -} - -int F::f2(F* this, int a) { // expected-error {{conflicting types for 'f2'}} - return a; -} - -int main(){ - Foo foo; - foo.a = 1; - foo.f2(); - foo.f2(1); // expected-warning {{incompatible integer to pointer conversion passing 'int' to parameter of type 'F *' (aka 'struct Foo *')}} - return 0; -} \ No newline at end of file diff --git a/clang/test/BSC/pending/StaticMemberFunc.cbs b/clang/test/BSC/pending/StaticMemberFunc.cbs deleted file mode 100644 index f9b2068cfd7e..000000000000 --- a/clang/test/BSC/pending/StaticMemberFunc.cbs +++ /dev/null @@ -1,20 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics -typedef struct Foo{ - int a; -}Foo; - -int Foo::s1() { - return 1; -} - -int Foo::s2(struct Foo* other) { - return other->a; -} - -int main() { - struct Foo x = {0}; - Foo::s1(); - Foo::s2(&x); - return 0; -} \ No newline at end of file diff --git a/clang/test/BSC/pending/ThisParamCheck1.cbs b/clang/test/BSC/pending/ThisParamCheck1.cbs deleted file mode 100644 index 05281fbfb1fb..000000000000 --- a/clang/test/BSC/pending/ThisParamCheck1.cbs +++ /dev/null @@ -1,17 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -typedef struct Foo { - int a; -}Foo; - -typedef struct Bar { - int a; -}Bar; - -int Foo::getA(int b, struct Foo* this) { // expected-error {{'this' cannot be the name of a parameter}} - return this->a; -} - -int Foo::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} - return this->a; -} \ No newline at end of file diff --git a/clang/test/BSC/pending/ThisParamCheck2.cbs b/clang/test/BSC/pending/ThisParamCheck2.cbs deleted file mode 100644 index 1fee3762a580..000000000000 --- a/clang/test/BSC/pending/ThisParamCheck2.cbs +++ /dev/null @@ -1,21 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -typedef struct Foo{ - int a; -}Foo; - -int Foo::s1() { - return 1; -} - -int Foo::s2(struct Foo* other) { - return other->a; -} - -int main() { - struct Foo x = {0}; - x.s1(); // expected-error {{no member named 's1' in 'struct Foo'; did you mean to use '::' instead of '.'?}} - - x.s2(); // expected-error {{no member named 's2' in 'struct Foo'; did you mean to use '::' instead of '.'?}} - return 0; -} \ No newline at end of file -- Gitee From 9fbab67291eb84ec8af487f5ce6fc20835b66d63 Mon Sep 17 00:00:00 2001 From: MilMou Date: Tue, 7 Mar 2023 01:49:29 +0000 Subject: [PATCH 8/8] [BSC] Ambiguous declaration of BSCMethod Throw err when there is ambiguous declaration of BSCMethod --- .../clang/Basic/DiagnosticParseKinds.td | 1 + clang/include/clang/Parse/Parser.h | 1 + clang/lib/Parse/ParseDecl.cpp | 32 +++++++++++++++++-- clang/test/BSC/Method/ambiguous_1.cbs | 18 +++++++++++ clang/test/BSC/Method/ambiguous_2.cbs | 9 ++++++ clang/test/BSC/Method/ambiguous_3.cbs | 9 ++++++ clang/test/BSC/Method/ambiguous_4.cbs | 9 ++++++ clang/test/BSC/Method/definition_1.cbs | 4 --- 8 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 clang/test/BSC/Method/ambiguous_1.cbs create mode 100644 clang/test/BSC/Method/ambiguous_2.cbs create mode 100644 clang/test/BSC/Method/ambiguous_3.cbs create mode 100644 clang/test/BSC/Method/ambiguous_4.cbs diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 0ed80a481e78..81aed6408fb5 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1498,4 +1498,5 @@ def warn_max_tokens_total : Warning< def note_max_tokens_total_override : Note<"total token limit set here">; +def ambiguous_bscmethod_define : Error<"Ambiguous declaration of BSCMethod">; } // end of Parser diagnostics diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 6f53fea395be..3f6dc67f257c 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2363,6 +2363,7 @@ private: DeclSpecContext DSC = DeclSpecContext::DSC_normal, LateParsedAttrList *LateAttrs = nullptr, bool BSCScopeSpecFlag = false); void ParseBSCScopeSpecifiers(DeclSpec &DS); + bool IsBSCMethodAmbiguous(); bool DiagnoseMissingSemiAfterTagDefinition( DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext, LateParsedAttrList *LateAttrs = nullptr); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index f475e675c455..d9c892251ce7 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3047,8 +3047,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, SourceLocation Loc = Tok.getLocation(); - if (BSCMethodFlag && DS.hasTypeSpecifier()) - goto DoneWithDeclSpec; + if (BSCMethodFlag) { + if (DS.hasTypeSpecifier()) + goto DoneWithDeclSpec; + // if the method is unsinged long long::getA(){...}, which causes a + // misunderstanding on whether the BSCScopeSpec is long long or long, it + // throws out an error. + if (IsBSCMethodAmbiguous()) + Diag(Loc, diag::ambiguous_bscmethod_define); + } switch (Tok.getKind()) { default: @@ -5665,6 +5672,27 @@ static bool isPipeDeclerator(const Declarator &D) { return false; } +bool Parser::IsBSCMethodAmbiguous() { + assert(NextToken().isNot(tok::eof)); + if (GetLookAheadToken(2).isNot(tok::coloncolon)) { + bool FlagUnsigned = (Tok.is(tok::kw_unsigned) && + NextToken().isOneOf(tok::kw_int, tok::kw_short, + tok::kw_long, tok::kw_unsigned)); + bool FlagLong = + (Tok.is(tok::kw_long) && + NextToken().isOneOf(tok::kw_int, tok::kw_long, tok::kw_unsigned)); + bool FlagShort = + (Tok.is(tok::kw_short) && + NextToken().isOneOf(tok::kw_short, tok::kw_int, tok::kw_unsigned)); + bool FlagInt = + (Tok.is(tok::kw_int) && + NextToken().isOneOf(tok::kw_short, tok::kw_long, tok::kw_unsigned)); + if (FlagUnsigned || FlagLong || FlagShort || FlagInt) + return true; + } + return false; +} + /// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator /// is parsed by the function passed to it. Pass null, and the direct-declarator /// isn't parsed at all, making this function effectively parse the C++ diff --git a/clang/test/BSC/Method/ambiguous_1.cbs b/clang/test/BSC/Method/ambiguous_1.cbs new file mode 100644 index 000000000000..76aa5ce27c64 --- /dev/null +++ b/clang/test/BSC/Method/ambiguous_1.cbs @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + +long int::getA1() { + return 1; +}; + +unsigned int::getA2() { + return 1; +}; + +short int::getA3() { + return 1; +}; + +int main() { + return 0; +}; diff --git a/clang/test/BSC/Method/ambiguous_2.cbs b/clang/test/BSC/Method/ambiguous_2.cbs new file mode 100644 index 000000000000..298ea3a8d0c8 --- /dev/null +++ b/clang/test/BSC/Method/ambiguous_2.cbs @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +long long int::getA() { // expected-error {{Ambiguous declaration of BSCMethod}} + return 1; +}; + +int main() { + return 0; +}; diff --git a/clang/test/BSC/Method/ambiguous_3.cbs b/clang/test/BSC/Method/ambiguous_3.cbs new file mode 100644 index 000000000000..a87e50fb8c23 --- /dev/null +++ b/clang/test/BSC/Method/ambiguous_3.cbs @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +short short int::getA() { // expected-error {{Ambiguous declaration of BSCMethod}} + return 1; +}; + +int main() { + return 0; +}; diff --git a/clang/test/BSC/Method/ambiguous_4.cbs b/clang/test/BSC/Method/ambiguous_4.cbs new file mode 100644 index 000000000000..eba2ecaff588 --- /dev/null +++ b/clang/test/BSC/Method/ambiguous_4.cbs @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +unsigned long int::getA() { // expected-error {{Ambiguous declaration of BSCMethod}} + return 1; +}; + +int main() { + return 0; +}; diff --git a/clang/test/BSC/Method/definition_1.cbs b/clang/test/BSC/Method/definition_1.cbs index 5a837692ec03..02be953ea3ed 100644 --- a/clang/test/BSC/Method/definition_1.cbs +++ b/clang/test/BSC/Method/definition_1.cbs @@ -53,10 +53,6 @@ int short::getA0() { return 0; } -unsigned long int::getAa() { - return 0; -} - int main() { return 0; } -- Gitee