From 9f6f6335cca6c43e564338b41fe5d7d69ba05951 Mon Sep 17 00:00:00 2001 From: yangdiangzb Date: Thu, 23 Feb 2023 10:50:13 +0000 Subject: [PATCH 01/13] [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 02/13] [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 03/13] [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 04/13] !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 05/13] !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 06/13] !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 07/13] !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 08/13] [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 From 3e44351820a7426f118f38b3fd339565c6768676 Mon Sep 17 00:00:00 2001 From: zhangyi Date: Thu, 16 Feb 2023 15:59:12 +0800 Subject: [PATCH 09/13] [BSC] add interface keyword add interface keyword "kw_interface" design InterfaceDecl and support parsing of it and part of sema. now we can parse : interface I { void f(); int g(); } todo: need to verify decls in interface body, only function declarations are allowed, but now we allow everything like RecordDecl does. --- clang/include/clang/AST/ASTContext.h | 2 + clang/include/clang/AST/Decl.h | 240 ++++++ clang/include/clang/AST/DeclBase.h | 59 ++ clang/include/clang/AST/RecursiveASTVisitor.h | 14 + clang/include/clang/AST/Type.h | 33 +- clang/include/clang/AST/TypeLoc.h | 7 + clang/include/clang/AST/TypeProperties.td | 11 + clang/include/clang/Basic/DeclNodes.td | 1 + clang/include/clang/Basic/Specifiers.h | 1 + clang/include/clang/Basic/TokenKinds.def | 3 + clang/include/clang/Basic/TypeNodes.td | 1 + clang/include/clang/Parse/Parser.h | 8 + clang/include/clang/Sema/DeclSpec.h | 3 +- clang/include/clang/Sema/Sema.h | 4 +- .../clang/Serialization/TypeBitCodes.def | 1 + clang/lib/AST/ASTContext.cpp | 23 +- clang/lib/AST/ASTImporter.cpp | 9 + clang/lib/AST/ASTStructuralEquivalence.cpp | 1 + clang/lib/AST/Decl.cpp | 123 ++- clang/lib/AST/DeclBase.cpp | 1 + clang/lib/AST/DeclCXX.cpp | 2 + clang/lib/AST/ExprConstant.cpp | 2 + clang/lib/AST/ItaniumMangle.cpp | 7 + clang/lib/AST/MicrosoftMangle.cpp | 5 + clang/lib/AST/ODRHash.cpp | 1 + clang/lib/AST/Type.cpp | 11 +- clang/lib/AST/TypePrinter.cpp | 7 + clang/lib/CodeGen/CGDecl.cpp | 1 + clang/lib/CodeGen/CodeGenFunction.cpp | 2 + clang/lib/CodeGen/CodeGenTypes.cpp | 1 + clang/lib/CodeGen/ItaniumCXXABI.cpp | 2 + clang/lib/Index/IndexSymbol.cpp | 2 + clang/lib/Index/USRGeneration.cpp | 3 + clang/lib/Lex/Lexer.cpp | 13 +- clang/lib/Parse/ParseDecl.cpp | 708 +++++++++++++++++- clang/lib/Parse/ParseDeclCXX.cpp | 6 +- clang/lib/Parse/ParseExpr.cpp | 6 + clang/lib/Parse/ParseExprCXX.cpp | 2 +- clang/lib/Parse/Parser.cpp | 4 +- clang/lib/Sema/DeclSpec.cpp | 2 + clang/lib/Sema/SemaCodeComplete.cpp | 4 + clang/lib/Sema/SemaDecl.cpp | 30 +- clang/lib/Sema/SemaExpr.cpp | 1 + clang/lib/Sema/SemaLookup.cpp | 3 + clang/lib/Sema/SemaTemplate.cpp | 4 + clang/lib/Sema/SemaTemplateDeduction.cpp | 2 + .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 4 + clang/lib/Sema/SemaTemplateVariadic.cpp | 1 + clang/lib/Sema/SemaType.cpp | 2 + clang/lib/Sema/TreeTransform.h | 28 + clang/lib/Serialization/ASTCommon.cpp | 1 + clang/lib/Serialization/ASTReader.cpp | 4 + clang/lib/Serialization/ASTReaderDecl.cpp | 20 + clang/lib/Serialization/ASTWriter.cpp | 4 + clang/tools/libclang/CIndex.cpp | 2 + clang/tools/libclang/CIndexCXX.cpp | 1 + 56 files changed, 1423 insertions(+), 20 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 359f666c7f49..aae2b50bf9dc 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1449,6 +1449,8 @@ public: QualType getEnumType(const EnumDecl *Decl) const; + QualType getInterfaceType(const InterfaceDecl *Decl) const; + QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const; QualType getAttributedType(attr::Kind attrKind, diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 254e050b7777..cb03c816911e 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -3472,6 +3472,7 @@ public: bool isClass() const { return getTagKind() == TTK_Class; } bool isUnion() const { return getTagKind() == TTK_Union; } bool isEnum() const { return getTagKind() == TTK_Enum; } + bool isInterfaceBSC() const { return getTagKind() == TTK_Interface_bsc; } /// Is this tag type named, either directly or via being defined in /// a typedef of this type? @@ -4072,6 +4073,245 @@ private: void LoadFieldsFromExternalStorage() const; }; +class InterfaceDecl : public TagDecl { + // This class stores some data in DeclContext::RecordDeclBits + // to save some space. Use the provided accessors to access it. +public: + friend class DeclContext; + /// Enum that represents the different ways arguments are passed to and + /// returned from function calls. This takes into account the target-specific + /// and version-specific rules along with the rules determined by the + /// language. + enum ArgPassingKind : unsigned { + /// The argument of this type can be passed directly in registers. + APK_CanPassInRegs, + + /// The argument of this type cannot be passed directly in registers. + /// Records containing this type as a subobject are not forced to be passed + /// indirectly. This value is used only in C++. This value is required by + /// C++ because, in uncommon situations, it is possible for a class to have + /// only trivial copy/move constructors even when one of its subobjects has + /// a non-trivial copy/move constructor (if e.g. the corresponding copy/move + /// constructor in the derived class is deleted). + APK_CannotPassInRegs, + + /// The argument of this type cannot be passed directly in registers. + /// Records containing this type as a subobject are forced to be passed + /// indirectly. + APK_CanNeverPassInRegs + }; + +protected: + InterfaceDecl(Kind DK, TagKind TK, const ASTContext &C, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + InterfaceDecl *PrevDecl); + +public: + static InterfaceDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, InterfaceDecl* PrevDecl = nullptr); + static InterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID); + + InterfaceDecl *getPreviousDecl() { + return cast_or_null( + static_cast(this)->getPreviousDecl()); + } + const InterfaceDecl *getPreviousDecl() const { + return const_cast(this)->getPreviousDecl(); + } + + InterfaceDecl *getMostRecentDecl() { + return cast(static_cast(this)->getMostRecentDecl()); + } + const InterfaceDecl *getMostRecentDecl() const { + return const_cast(this)->getMostRecentDecl(); + } + + bool hasFlexibleArrayMember() const { + return InterfaceDeclBits.HasFlexibleArrayMember; + } + + void setHasFlexibleArrayMember(bool V) { + InterfaceDeclBits.HasFlexibleArrayMember = V; + } + + /// Whether this is an anonymous struct or union. To be an anonymous + /// struct or union, it must have been declared without a name and + /// there must be no objects of this type declared, e.g., + /// @code + /// union { int i; float f; }; + /// @endcode + /// is an anonymous union but neither of the following are: + /// @code + /// union X { int i; float f; }; + /// union { int i; float f; } obj; + /// @endcode + bool isAnonymousStructOrUnion() const { + return InterfaceDeclBits.AnonymousStructOrUnion; + } + + void setAnonymousStructOrUnion(bool Anon) { + InterfaceDeclBits.AnonymousStructOrUnion = Anon; + } + + bool hasObjectMember() const { return InterfaceDeclBits.HasObjectMember; } + void setHasObjectMember(bool val) { InterfaceDeclBits.HasObjectMember = val; } + + bool hasVolatileMember() const { return InterfaceDeclBits.HasVolatileMember; } + + void setHasVolatileMember(bool val) { + InterfaceDeclBits.HasVolatileMember = val; + } + + bool hasLoadedFieldsFromExternalStorage() const { + return InterfaceDeclBits.LoadedFieldsFromExternalStorage; + } + + void setHasLoadedFieldsFromExternalStorage(bool val) const { + InterfaceDeclBits.LoadedFieldsFromExternalStorage = val; + } + + /// Functions to query basic properties of non-trivial C structs. + bool isNonTrivialToPrimitiveDefaultInitialize() const { + return InterfaceDeclBits.NonTrivialToPrimitiveDefaultInitialize; + } + + void setNonTrivialToPrimitiveDefaultInitialize(bool V) { + InterfaceDeclBits.NonTrivialToPrimitiveDefaultInitialize = V; + } + + bool isNonTrivialToPrimitiveCopy() const { + return InterfaceDeclBits.NonTrivialToPrimitiveCopy; + } + + void setNonTrivialToPrimitiveCopy(bool V) { + InterfaceDeclBits.NonTrivialToPrimitiveCopy = V; + } + + bool isNonTrivialToPrimitiveDestroy() const { + return InterfaceDeclBits.NonTrivialToPrimitiveDestroy; + } + + void setNonTrivialToPrimitiveDestroy(bool V) { + InterfaceDeclBits.NonTrivialToPrimitiveDestroy = V; + } + + bool hasNonTrivialToPrimitiveDefaultInitializeCUnion() const { + return InterfaceDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion; + } + + void setHasNonTrivialToPrimitiveDefaultInitializeCUnion(bool V) { + InterfaceDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion = V; + } + + bool hasNonTrivialToPrimitiveDestructCUnion() const { + return InterfaceDeclBits.HasNonTrivialToPrimitiveDestructCUnion; + } + + void setHasNonTrivialToPrimitiveDestructCUnion(bool V) { + InterfaceDeclBits.HasNonTrivialToPrimitiveDestructCUnion = V; + } + + bool hasNonTrivialToPrimitiveCopyCUnion() const { + return InterfaceDeclBits.HasNonTrivialToPrimitiveCopyCUnion; + } + + void setHasNonTrivialToPrimitiveCopyCUnion(bool V) { + InterfaceDeclBits.HasNonTrivialToPrimitiveCopyCUnion = V; + } + + using field_iterator = specific_decl_iterator; + using field_range = llvm::iterator_range>; + + bool isOrContainsUnion() const; + + field_range fields() const { return field_range(field_begin(), field_end()); } + field_iterator field_begin() const; + + field_iterator field_end() const { + return field_iterator(decl_iterator()); + } + + // Whether there are any fields (non-static data members) in this record. + bool field_empty() const { + return field_begin() == field_end(); + } + + /// Determine whether this class can be passed in registers. In C++ mode, + /// it must have at least one trivial, non-deleted copy or move constructor. + /// FIXME: This should be set as part of completeDefinition. + virtual void completeDefinition(); + + bool canPassInRegisters() const { + return getArgPassingRestrictions() == APK_CanPassInRegs; + } + + ArgPassingKind getArgPassingRestrictions() const { + return static_cast(InterfaceDeclBits.ArgPassingRestrictions); + } + + void setArgPassingRestrictions(ArgPassingKind Kind) { + InterfaceDeclBits.ArgPassingRestrictions = Kind; + } + + bool isParamDestroyedInCallee() const { + return InterfaceDeclBits.ParamDestroyedInCallee; + } + + void setParamDestroyedInCallee(bool V) { + InterfaceDeclBits.ParamDestroyedInCallee = V; + } + + bool isInjectedClassName() const; + + /// Determine whether this record is a class describing a lambda + /// function object. + bool isLambda() const; + + /// Determine whether this record is a record for captured variables in + /// CapturedStmt construct. + bool isCapturedRecord() const; + + /// Mark the record as a record for captured variables in CapturedStmt + /// construct. + void setCapturedRecord(); + + /// Returns the RecordDecl that actually defines + /// this struct/union/class. When determining whether or not a + /// struct/union/class is completely defined, one should use this + /// method as opposed to 'isCompleteDefinition'. + /// 'isCompleteDefinition' indicates whether or not a specific + /// RecordDecl is a completed definition, not whether or not the + /// record type is defined. This method returns NULL if there is + /// no RecordDecl that defines the struct/union/tag. + InterfaceDecl *getDefinition() const { + return cast_or_null(TagDecl::getDefinition()); + } + + + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { + return K == Interface; + } + + bool isMsStruct(const ASTContext &C) const; + + /// Whether we are allowed to insert extra padding between fields. + /// These padding are added to help AddressSanitizer detect + /// intra-object-overflow bugs. + bool mayInsertExtraPadding(bool EmitRemark = false) const; + + /// Finds the first data member which has a name. + /// nullptr is returned if no named data member exists. + const FieldDecl *findFirstNamedDataMember() const; + +private: + /// Deserialize just the fields. + void LoadFieldsFromExternalStorage() const; +}; + class FileScopeAsmDecl : public Decl { StringLiteral *AsmString; SourceLocation RParenLoc; diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index e0a75d099fbe..6b8187dd6743 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -1488,6 +1488,60 @@ class DeclContext { /// Number of non-inherited bits in RecordDeclBitfields. enum { NumRecordDeclBits = 14 }; + /// Stores the bits used by RecordDecl. + /// If modified NumRecordDeclBits and the accessor + /// methods in RecordDecl should be updated appropriately. + class InterfaceDeclBitfields { + friend class InterfaceDecl; + /// For the bits in DeclContextBitfields. + uint64_t : NumDeclContextBits; + /// For the bits in TagDeclBitfields. + uint64_t : NumTagDeclBits; + + /// This is true if this struct ends with a flexible + /// array member (e.g. int X[]) or if this union contains a struct that does. + /// If so, this cannot be contained in arrays or other structs as a member. + uint64_t HasFlexibleArrayMember : 1; + + /// Whether this is the type of an anonymous struct or union. + uint64_t AnonymousStructOrUnion : 1; + + /// This is true if this struct has at least one member + /// containing an Objective-C object pointer type. + uint64_t HasObjectMember : 1; + + /// This is true if struct has at least one member of + /// 'volatile' type. + uint64_t HasVolatileMember : 1; + + /// Whether the field declarations of this record have been loaded + /// from external storage. To avoid unnecessary deserialization of + /// methods/nested types we allow deserialization of just the fields + /// when needed. + mutable uint64_t LoadedFieldsFromExternalStorage : 1; + + /// Basic properties of non-trivial C structs. + uint64_t NonTrivialToPrimitiveDefaultInitialize : 1; + uint64_t NonTrivialToPrimitiveCopy : 1; + uint64_t NonTrivialToPrimitiveDestroy : 1; + + /// The following bits indicate whether this is or contains a C union that + /// is non-trivial to default-initialize, destruct, or copy. These bits + /// imply the associated basic non-triviality predicates declared above. + uint64_t HasNonTrivialToPrimitiveDefaultInitializeCUnion : 1; + uint64_t HasNonTrivialToPrimitiveDestructCUnion : 1; + uint64_t HasNonTrivialToPrimitiveCopyCUnion : 1; + + /// Indicates whether this struct is destroyed in the callee. + uint64_t ParamDestroyedInCallee : 1; + + /// Represents the way this type is passed to a function. + uint64_t ArgPassingRestrictions : 2; + }; + + /// Number of non-inherited bits in RecordDeclBitfields. + enum { NumInterfaceDeclBits = 14 }; + /// Stores the bits used by OMPDeclareReductionDecl. /// If modified NumOMPDeclareReductionDeclBits and the accessor /// methods in OMPDeclareReductionDecl should be updated appropriately. @@ -1761,6 +1815,7 @@ protected: ObjCContainerDeclBitfields ObjCContainerDeclBits; LinkageSpecDeclBitfields LinkageSpecDeclBits; BlockDeclBitfields BlockDeclBits; + InterfaceDeclBitfields InterfaceDeclBits; static_assert(sizeof(DeclContextBitfields) <= 8, "DeclContextBitfields is larger than 8 bytes!"); @@ -1898,6 +1953,10 @@ public: getDeclKind() <= Decl::lastRecord; } + bool isInterface() const { + return getDeclKind() == Decl::Interface; + } + bool isNamespace() const { return getDeclKind() == Decl::Namespace; } bool isStdNamespace() const; diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 55f3253e6920..e8405e418176 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -485,6 +485,7 @@ private: unsigned Count); bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); bool TraverseRecordHelper(RecordDecl *D); + bool TraverseInterfaceHelper(InterfaceDecl *D); bool TraverseCXXRecordHelper(CXXRecordDecl *D); bool TraverseDeclaratorHelper(DeclaratorDecl *D); bool TraverseDeclContextHelper(DeclContext *DC); @@ -1004,6 +1005,7 @@ DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, { }) DEF_TRAVERSE_TYPE(RecordType, {}) +DEF_TRAVERSE_TYPE(InterfaceType, {}) DEF_TRAVERSE_TYPE(EnumType, {}) DEF_TRAVERSE_TYPE(TemplateTypeParmType, {}) DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { @@ -1282,6 +1284,7 @@ DEF_TRAVERSE_TYPELOC(DeducedTemplateSpecializationType, { DEF_TRAVERSE_TYPELOC(RecordType, {}) DEF_TRAVERSE_TYPELOC(EnumType, {}) +DEF_TRAVERSE_TYPELOC(InterfaceType, {}) DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {}) DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { TRY_TO(TraverseType(TL.getTypePtr()->getReplacementType())); @@ -1853,6 +1856,16 @@ bool RecursiveASTVisitor::TraverseRecordHelper(RecordDecl *D) { return true; } +template +bool RecursiveASTVisitor::TraverseInterfaceHelper(InterfaceDecl *D) { + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the type, not something that was written in the source. + + TRY_TO(TraverseDeclTemplateParameterLists(D)); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + return true; +} + template bool RecursiveASTVisitor::TraverseCXXBaseSpecifier( const CXXBaseSpecifier &Base) { @@ -1875,6 +1888,7 @@ bool RecursiveASTVisitor::TraverseCXXRecordHelper(CXXRecordDecl *D) { } DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); }) +DEF_TRAVERSE_DECL(InterfaceDecl, { TRY_TO(TraverseInterfaceHelper(D)); }) DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 319d3850346b..e254496337a1 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -121,6 +121,7 @@ class ObjCProtocolDecl; class ObjCTypeParamDecl; struct PrintingPolicy; class RecordDecl; +class InterfaceDecl; class Stmt; class TagDecl; class TemplateArgument; @@ -4596,7 +4597,7 @@ public: bool isBeingDefined() const; static bool classof(const Type *T) { - return T->getTypeClass() == Enum || T->getTypeClass() == Record; + return T->getTypeClass() == Enum || T->getTypeClass() == Record || T->getTypeClass() == Interface; } }; @@ -4626,6 +4627,30 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Record; } }; +class InterfaceType : public TagType { +protected: + friend class ASTContext; // ASTContext creates these. + + explicit InterfaceType(const InterfaceDecl *D) + : TagType(Interface, reinterpret_cast(D), QualType()) {} + explicit InterfaceType(TypeClass TC, InterfaceDecl *D) + : TagType(TC, reinterpret_cast(D), QualType()) {} + +public: + InterfaceDecl *getDecl() const { + return reinterpret_cast(TagType::getDecl()); + } + + /// Recursively check all fields in the record for const-ness. If any field + /// is declared const, return true. Otherwise, return false. + bool hasConstFields() const; + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { return T->getTypeClass() == Interface; } +}; + /// A helper class that allows the use of isa/cast/dyncast /// to detect TagType objects of enums. class EnumType : public TagType { @@ -5311,7 +5336,9 @@ enum TagTypeKind { TTK_Class, /// The "enum" keyword. - TTK_Enum + TTK_Enum, + + TTK_Interface_bsc }; /// The elaboration keyword that precedes a qualified type name or @@ -5332,6 +5359,8 @@ enum ElaboratedTypeKeyword { /// The "enum" keyword introduces the elaborated-type-specifier. ETK_Enum, + ETK_Interface_bsc, + /// The "typename" keyword precedes the qualified type name, e.g., /// \c typename T::type. ETK_Typename, diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 65e95d52c303..ae9d9082efb3 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -722,6 +722,13 @@ public: RecordDecl *getDecl() const { return getTypePtr()->getDecl(); } }; +class InterfaceTypeLoc : public InheritingConcreteTypeLoc { +public: + InterfaceDecl *getDecl() const { return getTypePtr()->getDecl(); } +}; + /// Wrapper for source info for enum types. class EnumTypeLoc : public InheritingConcreteTypeLoc; } +let Class = InterfaceType in { + def : Creator<[{ + auto interface = cast(declaration); + QualType result = ctx.getInterfaceType(interface); + if (dependent) + const_cast(result.getTypePtr()) + ->addDependence(TypeDependence::DependentInstantiation); + return result; + }]>; +} + let Class = ElaboratedType in { def : Property<"keyword", ElaboratedTypeKeyword> { let Read = [{ node->getKeyword() }]; diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td index 9f60363e7b92..0ffb95c89168 100644 --- a/clang/include/clang/Basic/DeclNodes.td +++ b/clang/include/clang/Basic/DeclNodes.td @@ -32,6 +32,7 @@ def Named : DeclNode; def ClassTemplateSpecialization : DeclNode; def ClassTemplatePartialSpecialization : DeclNode; + def Interface : DeclNode; def TemplateTypeParm : DeclNode; def Value : DeclNode; def EnumConstant : DeclNode; diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index c2736f90b1f5..af993becea38 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -78,6 +78,7 @@ namespace clang { TST_auto_type, // __auto_type extension TST_unknown_anytype, // __unknown_anytype extension TST_atomic, // C11 _Atomic + TST_interface_bsc, #define GENERIC_IMAGE_TYPE(ImgType, Id) TST_##ImgType##_t, // OpenCL image types #include "clang/Basic/OpenCLImageTypes.def" TST_error // erroneous type diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index b6e7b335bfb7..8b8e30e56fd8 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -328,6 +328,9 @@ KEYWORD(__func__ , KEYALL) KEYWORD(__objc_yes , KEYALL) KEYWORD(__objc_no , KEYALL) +KEYWORD(interface , KEYALL) +KEYWORD(implements , KEYALL) + // C++ 2.11p1: Keywords. KEYWORD(asm , KEYCXX|KEYGNU) diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td index 011394c3ef45..2211e474b364 100644 --- a/clang/include/clang/Basic/TypeNodes.td +++ b/clang/include/clang/Basic/TypeNodes.td @@ -87,6 +87,7 @@ def DecltypeType : TypeNode, NeverCanonicalUnlessDependent; def UnaryTransformType : TypeNode, NeverCanonicalUnlessDependent; def TagType : TypeNode; def RecordType : TypeNode, LeafType; +def InterfaceType : TypeNode, LeafType; def EnumType : TypeNode, LeafType; def ElaboratedType : TypeNode, NeverCanonical; def AttributedType : TypeNode, NeverCanonical; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 3f6dc67f257c..d1ba07470d65 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2378,9 +2378,17 @@ private: void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, DeclSpecContext DSC); + void ParseInterfaceSpecifier(tok::TokenKind TagTokKind, + SourceLocation StartLoc, DeclSpec &DS, + const ParsedTemplateInfo &TemplateInfo, + AccessSpecifier AS, + bool EnteringContext, DeclSpecContext DSC, + ParsedAttributesWithRange &Attributes); void ParseEnumBody(SourceLocation StartLoc, Decl *TagDecl); void ParseStructUnionBody(SourceLocation StartLoc, DeclSpec::TST TagType, RecordDecl *TagDecl); + void ParseInterfaceBody(SourceLocation StartLoc, DeclSpec::TST TagType, + InterfaceDecl *TagDecl); void ParseStructDeclaration( ParsingDeclSpec &DS, diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index f57c94ff35a3..3c9bb18397e4 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -295,6 +295,7 @@ public: static const TST TST_auto_type = clang::TST_auto_type; static const TST TST_unknown_anytype = clang::TST_unknown_anytype; static const TST TST_atomic = clang::TST_atomic; + static const TST TST_interface_bsc = clang::TST_interface_bsc; #define GENERIC_IMAGE_TYPE(ImgType, Id) \ static const TST TST_##ImgType##_t = clang::TST_##ImgType##_t; #include "clang/Basic/OpenCLImageTypes.def" @@ -420,7 +421,7 @@ public: static bool isDeclRep(TST T) { return (T == TST_enum || T == TST_struct || T == TST_interface || T == TST_union || - T == TST_class); + T == TST_class || T == TST_interface_bsc); } DeclSpec(AttributeFactory &attrFactory) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b0c085d98044..a2a429d14279 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3003,7 +3003,7 @@ public: Decl *ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth); - FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart, + FieldDecl *HandleField(Scope *S, TagDecl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth, InClassInitStyle InitStyle, AccessSpecifier AS); @@ -3016,7 +3016,7 @@ public: FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T, TypeSourceInfo *TInfo, - RecordDecl *Record, SourceLocation Loc, + TagDecl *Record, SourceLocation Loc, bool Mutable, Expr *BitfieldWidth, InClassInitStyle InitStyle, SourceLocation TSSL, diff --git a/clang/include/clang/Serialization/TypeBitCodes.def b/clang/include/clang/Serialization/TypeBitCodes.def index e92e05810648..853ae40297a1 100644 --- a/clang/include/clang/Serialization/TypeBitCodes.def +++ b/clang/include/clang/Serialization/TypeBitCodes.def @@ -62,5 +62,6 @@ TYPE_BIT_CODE(ExtInt, EXT_INT, 50) TYPE_BIT_CODE(DependentExtInt, DEPENDENT_EXT_INT, 51) TYPE_BIT_CODE(ConstantMatrix, CONSTANT_MATRIX, 52) TYPE_BIT_CODE(DependentSizedMatrix, DEPENDENT_SIZE_MATRIX, 53) +TYPE_BIT_CODE(Interface, INTERFACE, 54) #undef TYPE_BIT_CODE diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index cb7f00abf9e9..15e335886901 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2232,6 +2232,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = llvm::alignTo(EIT->getNumBits(), Align); break; } + case Type::Interface: case Type::Record: case Type::Enum: { const auto *TT = cast(T); @@ -3459,6 +3460,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { case Type::ObjCObjectPointer: case Type::Record: case Type::Enum: + case Type::Interface: case Type::UnresolvedUsing: case Type::TypeOfExpr: case Type::TypeOf: @@ -4444,7 +4446,10 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const { } else if (const auto *Enum = dyn_cast(Decl)) { assert(Enum->isFirstDecl() && "enum has previous declaration"); return getEnumType(Enum); - } else if (const auto *Using = dyn_cast(Decl)) { + } else if (const auto *Interface = dyn_cast(Decl)) { + assert(Interface->isFirstDecl() && "interface has previous declaration"); + return getInterfaceType(Interface); + }else if (const auto *Using = dyn_cast(Decl)) { Type *newType = new (*this, TypeAlignment) UnresolvedUsingType(Using); Decl->TypeForDecl = newType; Types.push_back(newType); @@ -4483,6 +4488,19 @@ QualType ASTContext::getRecordType(const RecordDecl *Decl) const { return QualType(newType, 0); } +QualType ASTContext::getInterfaceType(const InterfaceDecl *Decl) const { + if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); + + if (const InterfaceDecl *PrevDecl = Decl->getPreviousDecl()) + if (PrevDecl->TypeForDecl) + return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0); + + auto *newType = new (*this, TypeAlignment) InterfaceType(Decl); + Decl->TypeForDecl = newType; + Types.push_back(newType); + return QualType(newType, 0); +} + QualType ASTContext::getEnumType(const EnumDecl *Decl) const { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); @@ -7495,6 +7513,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, S += RDecl->isUnion() ? ')' : '}'; return; } + case Type::Interface: + return; case Type::BlockPointer: { const auto *BT = T->castAs(); @@ -9787,6 +9807,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, return mergeFunctionTypes(LHS, RHS, OfBlockPointer, Unqualified); case Type::Record: case Type::Enum: + case Type::Interface: return {}; case Type::Builtin: // Only exactly equal builtin types are compatible, which is tested above. diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 943a8419cbc0..54dd43775837 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -361,6 +361,7 @@ namespace clang { ExpectedType VisitInjectedClassNameType(const InjectedClassNameType *T); // FIXME: DependentDecltypeType ExpectedType VisitRecordType(const RecordType *T); + ExpectedType VisitInterfaceType(const InterfaceType *T); ExpectedType VisitEnumType(const EnumType *T); ExpectedType VisitAttributedType(const AttributedType *T); ExpectedType VisitTemplateTypeParmType(const TemplateTypeParmType *T); @@ -1402,6 +1403,14 @@ ExpectedType ASTNodeImporter::VisitRecordType(const RecordType *T) { return Importer.getToContext().getTagDeclType(*ToDeclOrErr); } +ExpectedType ASTNodeImporter::VisitInterfaceType(const InterfaceType *T) { + Expected ToDeclOrErr = import(T->getDecl()); + if (!ToDeclOrErr) + return ToDeclOrErr.takeError(); + + return Importer.getToContext().getTagDeclType(*ToDeclOrErr); +} + ExpectedType ASTNodeImporter::VisitEnumType(const EnumType *T) { Expected ToDeclOrErr = import(T->getDecl()); if (!ToDeclOrErr) diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index d004e443ae06..57ff9a4678ed 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -1018,6 +1018,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case Type::Record: case Type::Enum: + case Type::Interface: if (!IsStructurallyEquivalent(Context, cast(T1)->getDecl(), cast(T2)->getDecl())) return false; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 80b9be706ac4..2de500b8bfe7 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1642,7 +1642,12 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS, OS << "(anonymous " << RD->getKindName() << ')'; else OS << *RD; - } else if (const auto *FD = dyn_cast(DC)) { + } else if (const auto *ID = dyn_cast(DC)) { + if (!ID->getIdentifier()) + OS << "(anonymous " << ID->getKindName() << ')'; + else + OS << *ID; + }else if (const auto *FD = dyn_cast(DC)) { const FunctionProtoType *FT = nullptr; if (FD->hasWrittenPrototype()) FT = dyn_cast(FD->getType()->castAs()); @@ -4509,6 +4514,40 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, return R; } +InterfaceDecl::InterfaceDecl(Kind DK, TagKind TK, const ASTContext &C, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + InterfaceDecl *PrevDecl) + : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) { + assert(classof(static_cast(this)) && "Invalid Kind!"); + setHasFlexibleArrayMember(false); + setAnonymousStructOrUnion(false); + setHasObjectMember(false); + setHasVolatileMember(false); + setHasLoadedFieldsFromExternalStorage(false); + setNonTrivialToPrimitiveDefaultInitialize(false); + setNonTrivialToPrimitiveCopy(false); + setNonTrivialToPrimitiveDestroy(false); + setHasNonTrivialToPrimitiveDefaultInitializeCUnion(false); + setHasNonTrivialToPrimitiveDestructCUnion(false); + setHasNonTrivialToPrimitiveCopyCUnion(false); + setParamDestroyedInCallee(false); + setArgPassingRestrictions(APK_CanPassInRegs); +} + +InterfaceDecl *InterfaceDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, InterfaceDecl* PrevDecl) { + InterfaceDecl *R = new (C, DC) InterfaceDecl(Interface, TK, C, DC, + StartLoc, IdLoc, Id, PrevDecl); + R->setMayHaveOutOfDateDef(C.getLangOpts().Modules); + + C.getTypeDeclType(R, PrevDecl); + return R; +} + + + RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { RecordDecl *R = new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(), @@ -4522,20 +4561,37 @@ bool RecordDecl::isInjectedClassName() const { cast(getDeclContext())->getDeclName() == getDeclName(); } +bool InterfaceDecl::isInjectedClassName() const { + return isImplicit() && getDeclName() && getDeclContext()->isInterface() && + cast(getDeclContext())->getDeclName() == getDeclName(); +} + bool RecordDecl::isLambda() const { if (auto RD = dyn_cast(this)) return RD->isLambda(); return false; } +bool InterfaceDecl::isLambda() const { + return false; +} + bool RecordDecl::isCapturedRecord() const { return hasAttr(); } +bool InterfaceDecl::isCapturedRecord() const { + return hasAttr(); +} + void RecordDecl::setCapturedRecord() { addAttr(CapturedRecordAttr::CreateImplicit(getASTContext())); } +void InterfaceDecl::setCapturedRecord() { + addAttr(CapturedRecordAttr::CreateImplicit(getASTContext())); +} + bool RecordDecl::isOrContainsUnion() const { if (isUnion()) return true; @@ -4551,6 +4607,10 @@ bool RecordDecl::isOrContainsUnion() const { return false; } +bool InterfaceDecl::isOrContainsUnion() const { + return false; +} + RecordDecl::field_iterator RecordDecl::field_begin() const { if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage()) LoadFieldsFromExternalStorage(); @@ -4558,6 +4618,13 @@ RecordDecl::field_iterator RecordDecl::field_begin() const { return field_iterator(decl_iterator(FirstDecl)); } +RecordDecl::field_iterator InterfaceDecl::field_begin() const { + if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage()) + LoadFieldsFromExternalStorage(); + + return field_iterator(decl_iterator(FirstDecl)); +} + /// completeDefinition - Notes that the definition of this type is now /// complete. void RecordDecl::completeDefinition() { @@ -4565,6 +4632,11 @@ void RecordDecl::completeDefinition() { TagDecl::completeDefinition(); } +void InterfaceDecl::completeDefinition() { + assert(!isCompleteDefinition() && "Cannot redefine interface!"); + TagDecl::completeDefinition(); +} + /// isMsStruct - Get whether or not this record uses ms_struct layout. /// This which can be turned on with an attribute, pragma, or the /// -mms-bitfields command-line option. @@ -4572,6 +4644,10 @@ bool RecordDecl::isMsStruct(const ASTContext &C) const { return hasAttr() || C.getLangOpts().MSBitfields == 1; } +bool InterfaceDecl::isMsStruct(const ASTContext &C) const { + return hasAttr() || C.getLangOpts().MSBitfields == 1; +} + void RecordDecl::LoadFieldsFromExternalStorage() const { ExternalASTSource *Source = getASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); @@ -4598,6 +4674,32 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { /*FieldsAlreadyLoaded=*/false); } +void InterfaceDecl::LoadFieldsFromExternalStorage() const { + ExternalASTSource *Source = getASTContext().getExternalSource(); + assert(hasExternalLexicalStorage() && Source && "No external storage?"); + + // Notify that we have a RecordDecl doing some initialization. + ExternalASTSource::Deserializing TheFields(Source); + + SmallVector Decls; + setHasLoadedFieldsFromExternalStorage(true); + Source->FindExternalLexicalDecls(this, [](Decl::Kind K) { + return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K); + }, Decls); + +#ifndef NDEBUG + // Check that all decls we got were FieldDecls. + for (unsigned i=0, e=Decls.size(); i != e; ++i) + assert(isa(Decls[i]) || isa(Decls[i])); +#endif + + if (Decls.empty()) + return; + + std::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls, + /*FieldsAlreadyLoaded=*/false); +} + bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const { ASTContext &Context = getASTContext(); const SanitizerMask EnabledAsanMask = Context.getLangOpts().Sanitize.Mask & @@ -4643,6 +4745,10 @@ bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const { return ReasonToReject < 0; } +bool InterfaceDecl::mayInsertExtraPadding(bool EmitRemark) const { + return false; +} + const FieldDecl *RecordDecl::findFirstNamedDataMember() const { for (const auto *I : fields()) { if (I->getIdentifier()) @@ -4658,6 +4764,21 @@ const FieldDecl *RecordDecl::findFirstNamedDataMember() const { return nullptr; } +const FieldDecl *InterfaceDecl::findFirstNamedDataMember() const { + for (const auto *I : fields()) { + if (I->getIdentifier()) + return I; + + if (const auto *RT = I->getType()->getAs()) + if (const FieldDecl *NamedDataMember = + RT->getDecl()->findFirstNamedDataMember()) + return NamedDataMember; + } + + // We didn't find a named data member. + return nullptr; +} + //===----------------------------------------------------------------------===// // BlockDecl Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 3e9d1d032b74..ebcc98b83251 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -798,6 +798,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Record: case CXXRecord: case Enum: + case Interface: return IDNS_Tag | IDNS_Type; case Namespace: diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index ec71d0fabe90..dd285c8ba85d 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -143,6 +143,8 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, return R; } + + CXXRecordDecl * CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 4b3258be0989..003fca25e245 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -11005,6 +11005,8 @@ EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) { case Type::Complex: return GCCTypeClass::Complex; + case Type::Interface: + return GCCTypeClass::ClassOrStruct; case Type::Record: return CanTy->isUnionType() ? GCCTypeClass::Union : GCCTypeClass::ClassOrStruct; diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 5cad84a96845..c4078d369642 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2151,6 +2151,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::Enum: case Type::Record: + case Type::Interface: mangleSourceNameWithAbiTags(cast(Ty)->getDecl()); break; @@ -3113,6 +3114,11 @@ void CXXNameMangler::mangleType(const EnumType *T) { void CXXNameMangler::mangleType(const RecordType *T) { mangleType(static_cast(T)); } + +void CXXNameMangler::mangleType(const InterfaceType *T) { + mangleType(static_cast(T)); +} + void CXXNameMangler::mangleType(const TagType *T) { mangleName(T->getDecl()); } @@ -3648,6 +3654,7 @@ void CXXNameMangler::mangleType(const DependentNameType *T) { case ETK_Struct: case ETK_Class: case ETK_Interface: + case ETK_Interface_bsc: Out << "Ts"; break; case ETK_Union: diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index df6c566abc7d..3de90205234b 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -2744,6 +2744,7 @@ void MicrosoftCXXNameMangler::mangleTagTypeKind(TagTypeKind TTK) { break; case TTK_Struct: case TTK_Interface: + case TTK_Interface_bsc: Out << 'U'; break; case TTK_Class: @@ -2762,6 +2763,10 @@ void MicrosoftCXXNameMangler::mangleType(const RecordType *T, Qualifiers, SourceRange) { mangleType(cast(T)->getDecl()); } +void MicrosoftCXXNameMangler::mangleType(const InterfaceType *T, Qualifiers, + SourceRange) { + mangleType(cast(T)->getDecl()); +} void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { mangleTagTypeKind(TD->getTagKind()); mangleName(TD); diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 9a8e84c4fde6..14415b87c7b3 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -1018,6 +1018,7 @@ public: void VisitRecordType(const RecordType *T) { VisitTagType(T); } void VisitEnumType(const EnumType *T) { VisitTagType(T); } + void VisitInterfaceType(const InterfaceType *T) { VisitTagType(T); } void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { ID.AddInteger(T->getNumArgs()); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 034e175f1352..31b98653cfba 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2795,6 +2795,7 @@ TypeWithKeyword::getKeywordForTypeSpec(unsigned TypeSpec) { case TST_interface: return ETK_Interface; case TST_union: return ETK_Union; case TST_enum: return ETK_Enum; + case TST_interface_bsc: return ETK_Interface_bsc; } } @@ -2806,6 +2807,7 @@ TypeWithKeyword::getTagTypeKindForTypeSpec(unsigned TypeSpec) { case TST_interface: return TTK_Interface; case TST_union: return TTK_Union; case TST_enum: return TTK_Enum; + case TST_interface_bsc: return TTK_Interface_bsc; } llvm_unreachable("Type specifier is not a tag type kind."); @@ -2819,6 +2821,7 @@ TypeWithKeyword::getKeywordForTagTypeKind(TagTypeKind Kind) { case TTK_Interface: return ETK_Interface; case TTK_Union: return ETK_Union; case TTK_Enum: return ETK_Enum; + case TTK_Interface_bsc: return ETK_Interface_bsc; } llvm_unreachable("Unknown tag type kind."); } @@ -2831,6 +2834,7 @@ TypeWithKeyword::getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword) { case ETK_Interface: return TTK_Interface; case ETK_Union: return TTK_Union; case ETK_Enum: return TTK_Enum; + case ETK_Interface_bsc: return TTK_Interface_bsc; case ETK_None: // Fall through. case ETK_Typename: llvm_unreachable("Elaborated type keyword is not a tag type kind."); @@ -2847,6 +2851,7 @@ TypeWithKeyword::KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword) { case ETK_Class: case ETK_Struct: case ETK_Interface: + case ETK_Interface_bsc: case ETK_Union: case ETK_Enum: return true; @@ -2863,6 +2868,7 @@ StringRef TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) { case ETK_Interface: return "__interface"; case ETK_Union: return "union"; case ETK_Enum: return "enum"; + case ETK_Interface_bsc: return "interface"; } llvm_unreachable("Unknown elaborated type keyword."); @@ -3836,7 +3842,8 @@ static CachedProperties computeCachedProperties(const Type *T) { return CachedProperties(ExternalLinkage, false); case Type::Record: - case Type::Enum: { + case Type::Enum: + case Type::Interface:{ const TagDecl *Tag = cast(T)->getDecl(); // C++ [basic.link]p8: @@ -3938,6 +3945,7 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) { case Type::Record: case Type::Enum: + case Type::Interface: return getDeclLinkageAndVisibility(cast(T)->getDecl()); case Type::Complex: @@ -4138,6 +4146,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::FunctionProto: case Type::FunctionNoProto: case Type::Record: + case Type::Interface: case Type::DeducedTemplateSpecialization: case Type::Enum: case Type::InjectedClassName: diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 25d7874b53fb..160183bfa887 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -218,6 +218,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::UnaryTransform: case Type::Record: case Type::Enum: + case Type::Interface: case Type::Elaborated: case Type::TemplateTypeParm: case Type::SubstTemplateTypeParmPack: @@ -1381,6 +1382,12 @@ void TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) { void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) {} +void TypePrinter::printInterfaceBefore(const InterfaceType *T, raw_ostream &OS) { + printTag(T->getDecl(), OS); +} + +void TypePrinter::printInterfaceAfter(const InterfaceType *T, raw_ostream &OS) {} + void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T, raw_ostream &OS) { TemplateTypeParmDecl *D = T->getDecl(); diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 0e8a9a289a38..db6e32b0f272 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -102,6 +102,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::Binding: llvm_unreachable("Declaration should not be in declstmts!"); case Decl::Record: // struct/union/class X; + case Decl::Interface: case Decl::CXXRecord: // struct/union/class X; [C++] if (CGDebugInfo *DI = getDebugInfo()) if (cast(D).getDefinition()) diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index b393c88f7751..77261b3552c6 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -265,6 +265,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) { case Type::IncompleteArray: case Type::VariableArray: case Type::Record: + case Type::Interface: case Type::ObjCObject: case Type::ObjCInterface: return TEK_Aggregate; @@ -2126,6 +2127,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { case Type::ConstantMatrix: case Type::Record: case Type::Enum: + case Type::Interface: case Type::Elaborated: case Type::TemplateSpecialization: case Type::ObjCTypeParam: diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 7537ac12f1c8..2173caf96d58 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -425,6 +425,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { llvm::Type *ResultType = nullptr; switch (Ty->getTypeClass()) { case Type::Record: // Handled above. + case Type::Interface: #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) #define NON_CANONICAL_TYPE(Class, Base) case Type::Class: diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 50fb30a95cbb..e8d3bc080051 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3424,6 +3424,7 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { VTableName = "_ZTVN10__cxxabiv120__function_type_infoE"; break; + case Type::Interface: case Type::Enum: // abi::__enum_type_info. VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE"; @@ -3687,6 +3688,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( // abi::__function_type_info adds no data members to std::type_info. break; + case Type::Interface: case Type::Enum: // Itanium C++ ABI 2.9.5p5: // abi::__enum_type_info adds no data members to std::type_info. diff --git a/clang/lib/Index/IndexSymbol.cpp b/clang/lib/Index/IndexSymbol.cpp index 0d2e557cdd36..88c66c5ac9c8 100644 --- a/clang/lib/Index/IndexSymbol.cpp +++ b/clang/lib/Index/IndexSymbol.cpp @@ -106,6 +106,8 @@ SymbolInfo index::getSymbolInfo(const Decl *D) { if (const TagDecl *TD = dyn_cast(D)) { switch (TD->getTagKind()) { + //TODO: make interface symbolkind + case TTK_Interface_bsc: case TTK_Struct: Info.Kind = SymbolKind::Struct; break; case TTK_Union: diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp index abaeb1a4232f..068f5c382bf0 100644 --- a/clang/lib/Index/USRGeneration.cpp +++ b/clang/lib/Index/USRGeneration.cpp @@ -510,6 +510,7 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) { switch (D->getTagKind()) { case TTK_Interface: + case TTK_Interface_bsc: case TTK_Class: case TTK_Struct: Out << "@ST"; break; case TTK_Union: Out << "@UT"; break; @@ -522,6 +523,7 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) { switch (D->getTagKind()) { case TTK_Interface: + case TTK_Interface_bsc: case TTK_Class: case TTK_Struct: Out << "@SP"; break; case TTK_Union: Out << "@UP"; break; @@ -534,6 +536,7 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) { if (!AlreadyStarted) { switch (D->getTagKind()) { case TTK_Interface: + case TTK_Interface_bsc: case TTK_Class: case TTK_Struct: Out << "@S"; break; case TTK_Union: Out << "@U"; break; diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 431e446c1f20..5dc4fd58416a 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -3225,7 +3225,18 @@ LexNextToken: } unsigned SizeTmp, SizeTmp2; // Temporaries for use in cases below. - + if (*CurPtr == 's' && *(CurPtr+1) == 't'){ + llvm::outs() << "xxxxxxxx" << "\n"; + } + if (*CurPtr == 'e' && *(CurPtr+1) == 'n'){ + llvm::outs() << "xxxxxxxx" << "\n"; + } + if (*CurPtr == 'c' && *(CurPtr+1) == 'l'){ + llvm::outs() << "xxxxxxxx" << "\n"; + } + if (*CurPtr == 'i' && *(CurPtr+1) == 'n' && *(CurPtr+2) == 't' && *(CurPtr+3) == 'e'){ + llvm::outs() << "xxxxxxxx" << "\n"; + } // Read a character, advancing over it. char Char = getAndAdvanceChar(CurPtr, Result); tok::TokenKind Kind; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index d9c892251ce7..3db8a59b0914 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1566,7 +1566,6 @@ void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs, SourceLocation CorrectLocation) { assert((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) || Tok.is(tok::kw_alignas)); - // Consume the attributes. SourceLocation Loc = Tok.getLocation(); ParseCXX11Attributes(Attrs); @@ -2599,6 +2598,9 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, TagKind=tok::kw___interface;break; case DeclSpec::TST_class: TagName="class" ; FixitTagName = "class " ;TagKind=tok::kw_class ;break; + case DeclSpec::TST_interface_bsc: + TagName="interface"; FixitTagName = "interface "; + TagKind=tok::kw_interface;break; } if (TagName) { @@ -3980,6 +3982,17 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSContext); continue; + case tok::kw_interface: { + ConsumeToken(); + ParsedAttributesWithRange Attributes(AttrFactory); + ParseInterfaceSpecifier(tok::kw_interface, Loc, DS, TemplateInfo, AS, + EnteringContext, DSContext, Attributes); + if (!Attributes.empty()) { + AttrsLastTime = true; + attrs.takeAllFrom(Attributes); + } + continue;} + // cv-qualifier: case tok::kw_const: isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID, @@ -4363,6 +4376,127 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); } +void Parser::ParseInterfaceBody(SourceLocation RecordLoc, + DeclSpec::TST TagType, InterfaceDecl *TagDecl) + { + PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc, + "parsing struct/union body"); + assert(!getLangOpts().CPlusPlus && "C++ declarations not supported"); + + BalancedDelimiterTracker T(*this, tok::l_brace); + if (T.consumeOpen()) + return; + + ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope); + Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); + + // While we still have something to read, read the declarations in the struct. + while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && + Tok.isNot(tok::eof)) { + // Each iteration of this loop reads one struct-declaration. + + // Check for extraneous top-level semicolon. + if (Tok.is(tok::semi)) { + ConsumeExtraSemi(InsideStruct, TagType); + continue; + } + + // Parse _Static_assert declaration. + if (Tok.isOneOf(tok::kw__Static_assert, tok::kw_static_assert)) { + SourceLocation DeclEnd; + ParseStaticAssertDeclaration(DeclEnd); + continue; + } + + if (Tok.is(tok::annot_pragma_pack)) { + HandlePragmaPack(); + continue; + } + + if (Tok.is(tok::annot_pragma_align)) { + HandlePragmaAlign(); + continue; + } + + if (Tok.is(tok::annot_pragma_openmp)) { + // Result can be ignored, because it must be always empty. + AccessSpecifier AS = AS_none; + ParsedAttributesWithRange Attrs(AttrFactory); + (void)ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs); + continue; + } + + if (tok::isPragmaAnnotation(Tok.getKind())) { + Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl) + << DeclSpec::getSpecifierName( + TagType, Actions.getASTContext().getPrintingPolicy()); + ConsumeAnnotationToken(); + continue; + } + + if (!Tok.is(tok::at)) { + auto CFieldCallback = [&](ParsingFieldDeclarator &FD) { + // Install the declarator into the current TagDecl. + Decl *Field = + Actions.ActOnField(getCurScope(), TagDecl, + FD.D.getDeclSpec().getSourceRange().getBegin(), + FD.D, FD.BitfieldSize); + FD.complete(Field); + }; + + // Parse all the comma separated declarators. + ParsingDeclSpec DS(*this); + ParseStructDeclaration(DS, CFieldCallback); + } else { // Handle @defs + ConsumeToken(); + if (!Tok.isObjCAtKeyword(tok::objc_defs)) { + Diag(Tok, diag::err_unexpected_at); + SkipUntil(tok::semi); + continue; + } + ConsumeToken(); + ExpectAndConsume(tok::l_paren); + if (!Tok.is(tok::identifier)) { + Diag(Tok, diag::err_expected) << tok::identifier; + SkipUntil(tok::semi); + continue; + } + SmallVector Fields; + Actions.ActOnDefs(getCurScope(), TagDecl, Tok.getLocation(), + Tok.getIdentifierInfo(), Fields); + ConsumeToken(); + ExpectAndConsume(tok::r_paren); + } + + if (TryConsumeToken(tok::semi)) + continue; + + if (Tok.is(tok::r_brace)) { + ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list); + break; + } + + ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list); + // Skip to end of block or statement to avoid ext-warning on extra ';'. + SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); + // If we stopped at a ';', eat it. + TryConsumeToken(tok::semi); + } + + T.consumeClose(); + + ParsedAttributes attrs(AttrFactory); + // If attributes exist after struct contents, parse them. + MaybeParseGNUAttributes(attrs); + + SmallVector FieldDecls(TagDecl->field_begin(), + TagDecl->field_end()); + + Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls, + T.getOpenLocation(), T.getCloseLocation(), attrs); + StructScope.Exit(); + Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); + } /// ParseEnumSpecifier /// enum-specifier: [C99 6.7.2.2] /// 'enum' identifier[opt] '{' enumerator-list '}' @@ -4768,6 +4902,574 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, Diag(StartLoc, DiagID) << PrevSpec; } +void Parser::ParseInterfaceSpecifier(tok::TokenKind TagTokKind, + SourceLocation StartLoc, DeclSpec &DS, + const ParsedTemplateInfo &TemplateInfo, + AccessSpecifier AS, + bool EnteringContext, DeclSpecContext DSC, + ParsedAttributesWithRange &Attributes) { + assert(TagTokKind == tok::kw_interface && "Not a class specifier"); + DeclSpec::TST TagType = DeclSpec::TST_interface_bsc; + if (Tok.is(tok::code_completion)) { + // Code completion for a struct, class, or union name. + Actions.CodeCompleteTag(getCurScope(), TagType); + return cutOffParsing(); + } + + // C++03 [temp.explicit] 14.7.2/8: + // The usual access checking rules do not apply to names used to specify + // explicit instantiations. + // + // As an extension we do not perform access checking on the names used to + // specify explicit specializations either. This is important to allow + // specializing traits classes for private types. + // + // Note that we don't suppress if this turns out to be an elaborated + // type specifier. + bool shouldDelayDiagsInTag = + (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation || + TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization); + SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag); + + ParsedAttributesWithRange attrs(AttrFactory); + // If attributes exist after tag, parse them. + MaybeParseGNUAttributes(attrs); + MaybeParseMicrosoftDeclSpecs(attrs); + + // Parse inheritance specifiers. + if (Tok.isOneOf(tok::kw___single_inheritance, + tok::kw___multiple_inheritance, + tok::kw___virtual_inheritance)) + ParseMicrosoftInheritanceClassAttributes(attrs); + + // If C++0x attributes exist here, parse them. + // FIXME: Are we consistent with the ordering of parsing of different + // styles of attributes? + MaybeParseCXX11Attributes(attrs); + + // Source location used by FIXIT to insert misplaced + // C++11 attributes + SourceLocation AttrFixitLoc = Tok.getLocation(); + + struct PreserveAtomicIdentifierInfoRAII { + PreserveAtomicIdentifierInfoRAII(Token &Tok, bool Enabled) + : AtomicII(nullptr) { + if (!Enabled) + return; + assert(Tok.is(tok::kw__Atomic)); + AtomicII = Tok.getIdentifierInfo(); + AtomicII->revertTokenIDToIdentifier(); + Tok.setKind(tok::identifier); + } + ~PreserveAtomicIdentifierInfoRAII() { + if (!AtomicII) + return; + AtomicII->revertIdentifierToTokenID(tok::kw__Atomic); + } + IdentifierInfo *AtomicII; + }; + + // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL + // implementation for VS2013 uses _Atomic as an identifier for one of the + // classes in . When we are parsing 'struct _Atomic', don't consider + // '_Atomic' to be a keyword. We are careful to undo this so that clang can + // use '_Atomic' in its own header files. + bool ShouldChangeAtomicToIdentifier = getLangOpts().MSVCCompat && + Tok.is(tok::kw__Atomic) && + TagType == DeclSpec::TST_struct; + PreserveAtomicIdentifierInfoRAII AtomicTokenGuard( + Tok, ShouldChangeAtomicToIdentifier); + + // Parse the (optional) nested-name-specifier. + CXXScopeSpec &SS = DS.getTypeSpecScope(); + if (getLangOpts().CPlusPlus) { + // "FOO : BAR" is not a potential typo for "FOO::BAR". In this context it + // is a base-specifier-list. + ColonProtectionRAIIObject X(*this); + + CXXScopeSpec Spec; + bool HasValidSpec = true; + if (ParseOptionalCXXScopeSpecifier(Spec, /*ObjectType=*/nullptr, + /*ObjectHadErrors=*/false, + EnteringContext)) { + DS.SetTypeSpecError(); + HasValidSpec = false; + } + if (Spec.isSet()) + if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) { + Diag(Tok, diag::err_expected) << tok::identifier; + HasValidSpec = false; + } + if (HasValidSpec) + SS = Spec; + } + + TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; + + auto RecoverFromUndeclaredTemplateName = [&](IdentifierInfo *Name, + SourceLocation NameLoc, + SourceRange TemplateArgRange, + bool KnownUndeclared) { + Diag(NameLoc, diag::err_explicit_spec_non_template) + << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) + << TagTokKind << Name << TemplateArgRange << KnownUndeclared; + + // Strip off the last template parameter list if it was empty, since + // we've removed its template argument list. + if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) { + if (TemplateParams->size() > 1) { + TemplateParams->pop_back(); + } else { + TemplateParams = nullptr; + const_cast(TemplateInfo).Kind = + ParsedTemplateInfo::NonTemplate; + } + } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { + // Pretend this is just a forward declaration. + TemplateParams = nullptr; + const_cast(TemplateInfo).Kind = + ParsedTemplateInfo::NonTemplate; + const_cast(TemplateInfo).TemplateLoc = + SourceLocation(); + const_cast(TemplateInfo).ExternLoc = + SourceLocation(); + } + }; + + // Parse the (optional) class name or simple-template-id. + IdentifierInfo *Name = nullptr; + SourceLocation NameLoc; + TemplateIdAnnotation *TemplateId = nullptr; + if (Tok.is(tok::identifier)) { + Name = Tok.getIdentifierInfo(); + NameLoc = ConsumeToken(); + + if (Tok.is(tok::less) && getLangOpts().CPlusPlus) { + // The name was supposed to refer to a template, but didn't. + // Eat the template argument list and try to continue parsing this as + // a class (or template thereof). + TemplateArgList TemplateArgs; + SourceLocation LAngleLoc, RAngleLoc; + if (ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, + RAngleLoc)) { + // We couldn't parse the template argument list at all, so don't + // try to give any location information for the list. + LAngleLoc = RAngleLoc = SourceLocation(); + } + RecoverFromUndeclaredTemplateName( + Name, NameLoc, SourceRange(LAngleLoc, RAngleLoc), false); + } + } else if (Tok.is(tok::annot_template_id)) { + TemplateId = takeTemplateIdAnnotation(Tok); + NameLoc = ConsumeAnnotationToken(); + + if (TemplateId->Kind == TNK_Undeclared_template) { + // Try to resolve the template name to a type template. May update Kind. + Actions.ActOnUndeclaredTypeTemplateName( + getCurScope(), TemplateId->Template, TemplateId->Kind, NameLoc, Name); + if (TemplateId->Kind == TNK_Undeclared_template) { + RecoverFromUndeclaredTemplateName( + Name, NameLoc, + SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc), true); + TemplateId = nullptr; + } + } + + if (TemplateId && !TemplateId->mightBeType()) { + // The template-name in the simple-template-id refers to + // something other than a type template. Give an appropriate + // error message and skip to the ';'. + SourceRange Range(NameLoc); + if (SS.isNotEmpty()) + Range.setBegin(SS.getBeginLoc()); + + // FIXME: Name may be null here. + Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template) + << TemplateId->Name << static_cast(TemplateId->Kind) << Range; + + DS.SetTypeSpecError(); + SkipUntil(tok::semi, StopBeforeMatch); + return; + } + } + + // There are four options here. + // - If we are in a trailing return type, this is always just a reference, + // and we must not try to parse a definition. For instance, + // [] () -> struct S { }; + // does not define a type. + // - If we have 'struct foo {...', 'struct foo :...', + // 'struct foo final :' or 'struct foo final {', then this is a definition. + // - If we have 'struct foo;', then this is either a forward declaration + // or a friend declaration, which have to be treated differently. + // - Otherwise we have something like 'struct foo xyz', a reference. + // + // We also detect these erroneous cases to provide better diagnostic for + // C++11 attributes parsing. + // - attributes follow class name: + // struct foo [[]] {}; + // - attributes appear before or after 'final': + // struct foo [[]] final [[]] {}; + // + // However, in type-specifier-seq's, things look like declarations but are + // just references, e.g. + // new struct s; + // or + // &T::operator struct s; + // For these, DSC is DeclSpecContext::DSC_type_specifier or + // DeclSpecContext::DSC_alias_declaration. + + // If there are attributes after class name, parse them. + MaybeParseCXX11Attributes(Attributes); + + const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); + Sema::TagUseKind TUK; + if (isDefiningTypeSpecifierContext(DSC) == AllowDefiningTypeSpec::No || + (getLangOpts().OpenMP && OpenMPDirectiveParsing)) + TUK = Sema::TUK_Reference; + else if (Tok.is(tok::l_brace) || + (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || + (isCXX11FinalKeyword() && + (NextToken().is(tok::l_brace) || NextToken().is(tok::colon)))) { + if (DS.isFriendSpecified()) { + // C++ [class.friend]p2: + // A class shall not be defined in a friend declaration. + Diag(Tok.getLocation(), diag::err_friend_decl_defines_type) + << SourceRange(DS.getFriendSpecLoc()); + + // Skip everything up to the semicolon, so that this looks like a proper + // friend class (or template thereof) declaration. + SkipUntil(tok::semi, StopBeforeMatch); + TUK = Sema::TUK_Friend; + } else { + // Okay, this is a class definition. + TUK = Sema::TUK_Definition; + } + } else if (isCXX11FinalKeyword() && (NextToken().is(tok::l_square) || + NextToken().is(tok::kw_alignas))) { + // We can't tell if this is a definition or reference + // until we skipped the 'final' and C++11 attribute specifiers. + TentativeParsingAction PA(*this); + + // Skip the 'final' keyword. + ConsumeToken(); + + // Skip C++11 attribute specifiers. + while (true) { + if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) { + ConsumeBracket(); + if (!SkipUntil(tok::r_square, StopAtSemi)) + break; + } else if (Tok.is(tok::kw_alignas) && NextToken().is(tok::l_paren)) { + ConsumeToken(); + ConsumeParen(); + if (!SkipUntil(tok::r_paren, StopAtSemi)) + break; + } else { + break; + } + } + + if (Tok.isOneOf(tok::l_brace, tok::colon)) + TUK = Sema::TUK_Definition; + else + TUK = Sema::TUK_Reference; + + PA.Revert(); + } else if (!isTypeSpecifier(DSC) && + (Tok.is(tok::semi) || + (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) { + TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration; + if (Tok.isNot(tok::semi)) { + const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy(); + // A semicolon was missing after this declaration. Diagnose and recover. + ExpectAndConsume(tok::semi, diag::err_expected_after, + DeclSpec::getSpecifierName(TagType, PPol)); + PP.EnterToken(Tok, /*IsReinject*/true); + Tok.setKind(tok::semi); + } + } else + TUK = Sema::TUK_Reference; + + // Forbid misplaced attributes. In cases of a reference, we pass attributes + // to caller to handle. + if (TUK != Sema::TUK_Reference) { + // If this is not a reference, then the only possible + // valid place for C++11 attributes to appear here + // is between class-key and class-name. If there are + // any attributes after class-name, we try a fixit to move + // them to the right place. + SourceRange AttrRange = Attributes.Range; + if (AttrRange.isValid()) { + Diag(AttrRange.getBegin(), diag::err_attributes_not_allowed) + << AttrRange + << FixItHint::CreateInsertionFromRange(AttrFixitLoc, + CharSourceRange(AttrRange, true)) + << FixItHint::CreateRemoval(AttrRange); + + // Recover by adding misplaced attributes to the attribute list + // of the class so they can be applied on the class later. + attrs.takeAllFrom(Attributes); + } + } + + // If this is an elaborated type specifier, and we delayed + // diagnostics before, just merge them into the current pool. + if (shouldDelayDiagsInTag) { + diagsFromTag.done(); + if (TUK == Sema::TUK_Reference) + diagsFromTag.redelay(); + } + + if (!Name && !TemplateId && (DS.getTypeSpecType() == DeclSpec::TST_error || + TUK != Sema::TUK_Definition)) { + if (DS.getTypeSpecType() != DeclSpec::TST_error) { + // We have a declaration or reference to an anonymous class. + Diag(StartLoc, diag::err_anon_type_definition) + << DeclSpec::getSpecifierName(TagType, Policy); + } + + // If we are parsing a definition and stop at a base-clause, continue on + // until the semicolon. Continuing from the comma will just trick us into + // thinking we are seeing a variable declaration. + if (TUK == Sema::TUK_Definition && Tok.is(tok::colon)) + SkipUntil(tok::semi, StopBeforeMatch); + else + SkipUntil(tok::comma, StopAtSemi); + return; + } + + // Create the tag portion of the class or class template. + DeclResult TagOrTempResult = true; // invalid + TypeResult TypeResult = true; // invalid + + bool Owned = false; + Sema::SkipBodyInfo SkipBody; + if (TemplateId) { + // Explicit specialization, class template partial specialization, + // or explicit instantiation. + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + if (TemplateId->isInvalid()) { + // Can't build the declaration. + } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && + TUK == Sema::TUK_Declaration) { + // This is an explicit instantiation of a class template. + ProhibitAttributes(attrs); + + TagOrTempResult = Actions.ActOnExplicitInstantiation( + getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, + TagType, StartLoc, SS, TemplateId->Template, + TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, + TemplateId->RAngleLoc, attrs); + + // Friend template-ids are treated as references unless + // they have template headers, in which case they're ill-formed + // (FIXME: "template friend class A::B;"). + // We diagnose this error in ActOnClassTemplateSpecialization. + } else if (TUK == Sema::TUK_Reference || + (TUK == Sema::TUK_Friend && + TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) { + ProhibitAttributes(attrs); + TypeResult = Actions.ActOnTagTemplateIdType(TUK, TagType, StartLoc, + SS, + TemplateId->TemplateKWLoc, + TemplateId->Template, + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->RAngleLoc); + } else { + // This is an explicit specialization or a class template + // partial specialization. + TemplateParameterLists FakedParamLists; + if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { + // This looks like an explicit instantiation, because we have + // something like + // + // template class Foo + // + // but it actually has a definition. Most likely, this was + // meant to be an explicit specialization, but the user forgot + // the '<>' after 'template'. + // It this is friend declaration however, since it cannot have a + // template header, it is most likely that the user meant to + // remove the 'template' keyword. + assert((TUK == Sema::TUK_Definition || TUK == Sema::TUK_Friend) && + "Expected a definition here"); + + if (TUK == Sema::TUK_Friend) { + Diag(DS.getFriendSpecLoc(), diag::err_friend_explicit_instantiation); + TemplateParams = nullptr; + } else { + SourceLocation LAngleLoc = + PP.getLocForEndOfToken(TemplateInfo.TemplateLoc); + Diag(TemplateId->TemplateNameLoc, + diag::err_explicit_instantiation_with_definition) + << SourceRange(TemplateInfo.TemplateLoc) + << FixItHint::CreateInsertion(LAngleLoc, "<>"); + + // Create a fake template parameter list that contains only + // "template<>", so that we treat this construct as a class + // template specialization. + FakedParamLists.push_back(Actions.ActOnTemplateParameterList( + 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, None, + LAngleLoc, nullptr)); + TemplateParams = &FakedParamLists; + } + } + + // Build the class template specialization. + TagOrTempResult = Actions.ActOnClassTemplateSpecialization( + getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(), + SS, *TemplateId, attrs, + MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] + : nullptr, + TemplateParams ? TemplateParams->size() : 0), + &SkipBody); + } + } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && + TUK == Sema::TUK_Declaration) { + // Explicit instantiation of a member of a class template + // specialization, e.g., + // + // template struct Outer::Inner; + // + ProhibitAttributes(attrs); + + TagOrTempResult = Actions.ActOnExplicitInstantiation( + getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, + TagType, StartLoc, SS, Name, NameLoc, attrs); + } else if (TUK == Sema::TUK_Friend && + TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) { + ProhibitAttributes(attrs); + + TagOrTempResult = Actions.ActOnTemplatedFriendTag( + getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, Name, + NameLoc, attrs, + MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, + TemplateParams ? TemplateParams->size() : 0)); + } else { + if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition) + ProhibitAttributes(attrs); + + if (TUK == Sema::TUK_Definition && + TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { + // If the declarator-id is not a template-id, issue a diagnostic and + // recover by ignoring the 'template' keyword. + Diag(Tok, diag::err_template_defn_explicit_instantiation) + << 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc); + TemplateParams = nullptr; + } + + bool IsDependent = false; + + // Don't pass down template parameter lists if this is just a tag + // reference. For example, we don't need the template parameters here: + // template class A *makeA(T t); + MultiTemplateParamsArg TParams; + if (TUK != Sema::TUK_Reference && TemplateParams) + TParams = + MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size()); + + stripTypeAttributesOffDeclSpec(attrs, DS, TUK); + + // Declaration or definition of a class type + TagOrTempResult = Actions.ActOnTag( + getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, attrs, AS, + DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, + SourceLocation(), false, clang::TypeResult(), + DSC == DeclSpecContext::DSC_type_specifier, + DSC == DeclSpecContext::DSC_template_param || + DSC == DeclSpecContext::DSC_template_type_arg, + &SkipBody); + + // If ActOnTag said the type was dependent, try again with the + // less common call. + if (IsDependent) { + assert(TUK == Sema::TUK_Reference || TUK == Sema::TUK_Friend); + TypeResult = Actions.ActOnDependentTag(getCurScope(), TagType, TUK, + SS, Name, StartLoc, NameLoc); + } + } + + // If there is a body, parse it and inform the actions module. + if (TUK == Sema::TUK_Definition) { + assert(Tok.is(tok::l_brace) || + (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || + isCXX11FinalKeyword()); + if (SkipBody.ShouldSkip) + SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType, + TagOrTempResult.get()); + else if (getLangOpts().CPlusPlus) + ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType, + TagOrTempResult.get()); + else { + Decl *D = + SkipBody.CheckSameAsPrevious ? SkipBody.New : TagOrTempResult.get(); + // Parse the definition body. + ParseInterfaceBody(StartLoc, TagType, cast(D)); + if (SkipBody.CheckSameAsPrevious && + !Actions.ActOnDuplicateDefinition(DS, TagOrTempResult.get(), + SkipBody)) { + DS.SetTypeSpecError(); + return; + } + } + } + + if (!TagOrTempResult.isInvalid()) + // Delayed processing of attributes. + Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs); + + const char *PrevSpec = nullptr; + unsigned DiagID; + bool Result; + if (!TypeResult.isInvalid()) { + Result = DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, + NameLoc.isValid() ? NameLoc : StartLoc, + PrevSpec, DiagID, TypeResult.get(), Policy); + } else if (!TagOrTempResult.isInvalid()) { + Result = DS.SetTypeSpecType(TagType, StartLoc, + NameLoc.isValid() ? NameLoc : StartLoc, + PrevSpec, DiagID, TagOrTempResult.get(), Owned, + Policy); + } else { + DS.SetTypeSpecError(); + return; + } + + if (Result) + Diag(StartLoc, DiagID) << PrevSpec; + + // At this point, we've successfully parsed a class-specifier in 'definition' + // form (e.g. "struct foo { int x; }". While we could just return here, we're + // going to look at what comes after it to improve error recovery. If an + // impossible token occurs next, we assume that the programmer forgot a ; at + // the end of the declaration and recover that way. + // + // Also enforce C++ [temp]p3: + // In a template-declaration which defines a class, no declarator + // is permitted. + // + // After a type-specifier, we don't expect a semicolon. This only happens in + // C, since definitions are not permitted in this context in C++. + if (TUK == Sema::TUK_Definition && + (getLangOpts().CPlusPlus || !isTypeSpecifier(DSC)) && + (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) { + if (Tok.isNot(tok::semi)) { + const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy(); + ExpectAndConsume(tok::semi, diag::err_expected_after, + DeclSpec::getSpecifierName(TagType, PPol)); + // Push this token back into the preprocessor and change our current token + // to ';' so that the rest of the code recovers as though there were an + // ';' after the definition. + PP.EnterToken(Tok, /*IsReinject=*/true); + Tok.setKind(tok::semi); + } + } +} + /// ParseEnumBody - Parse a {} enclosed enumerator-list. /// enumerator-list: /// enumerator @@ -4966,6 +5668,8 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const { // typedef-name case tok::annot_typename: + + case tok::kw_interface: return true; } } @@ -5044,6 +5748,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw_union: // enum-specifier case tok::kw_enum: + case tok::kw_interface: // type-qualifier case tok::kw_const: @@ -5211,6 +5916,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw___interface: // enum-specifier case tok::kw_enum: + case tok::kw_interface: // type-qualifier case tok::kw_const: diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 88ebb59f9a60..1566a37771d4 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1407,6 +1407,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TagType = DeclSpec::TST_interface; else if (TagTokKind == tok::kw_class) TagType = DeclSpec::TST_class; + else if (TagTokKind == tok::kw_interface) + TagType = DeclSpec::TST_interface_bsc; else { assert(TagTokKind == tok::kw_union && "Not a class specifier"); TagType = DeclSpec::TST_union; @@ -3206,10 +3208,12 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, SourceLocation AttrFixitLoc, ParsedAttributesWithRange &Attrs, unsigned TagType, Decl *TagDecl) { + // TODO: interface not here assert((TagType == DeclSpec::TST_struct || TagType == DeclSpec::TST_interface || TagType == DeclSpec::TST_union || - TagType == DeclSpec::TST_class) && "Invalid TagType!"); + TagType == DeclSpec::TST_class || + TagType == DeclSpec::TST_interface_bsc) && "Invalid TagType!"); llvm::TimeTraceScope TimeScope("ParseClass", [&]() { if (auto *TD = dyn_cast_or_null(TagDecl)) diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 6fb1a7dba79a..678bfd7d1b36 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1308,6 +1308,12 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind); ConsumeToken(); break; + + case tok::kw_interface: + case tok::kw_implements: + llvm::outs() << "You are parsing bsc keywords!!!" << "\n"; + break; + case tok::string_literal: // primary-expression: string-literal case tok::wide_string_literal: case tok::utf8_string_literal: diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 4b5703d79f28..aa0d2bb0c47f 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -152,7 +152,7 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType, /// /// \returns true if there was an error parsing a scope specifier bool Parser::ParseOptionalCXXScopeSpecifier( - CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors, + CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors, bool EnteringContext, bool *MayBePseudoDestructor, bool IsTypename, IdentifierInfo **LastII, bool OnlyNamespace, bool InUsingDeclaration) { assert(getLangOpts().CPlusPlus && diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 815d078f0c79..ab591c5287fc 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1070,7 +1070,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, return nullptr; // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" - // declaration-specifiers init-declarator-list[opt] ';' + // declaration-specifiers init-decnlarator-list[opt] ';' if (Tok.is(tok::semi)) { auto LengthOfTSTToken = [](DeclSpec::TST TKind) { assert(DeclSpec::isDeclRep(TKind)); @@ -1085,6 +1085,8 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, return 4; case DeclSpec::TST_interface: return 9; + case DeclSpec::TST_interface_bsc: + return 9; default: llvm_unreachable("we only expect to get the length of the class/struct/union/enum"); } diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index d6639e900f7b..9410511d8102 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -367,6 +367,7 @@ bool Declarator::isDeclarationOfFunction() const { case TST_extint: case TST_struct: case TST_interface: + case TST_interface_bsc: case TST_union: case TST_unknown_anytype: case TST_unspecified: @@ -567,6 +568,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, case DeclSpec::TST_union: return "union"; case DeclSpec::TST_struct: return "struct"; case DeclSpec::TST_interface: return "__interface"; + case DeclSpec::TST_interface_bsc: return "interface"; case DeclSpec::TST_typename: return "type-name"; case DeclSpec::TST_typeofType: case DeclSpec::TST_typeofExpr: return "typeof"; diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index be04970979b3..9810825775c2 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -1903,6 +1903,8 @@ static const char *GetCompletionTypeString(QualType T, ASTContext &Context, return "union "; case TTK_Enum: return "enum "; + case TTK_Interface_bsc: + return "interface "; } } } @@ -3906,6 +3908,7 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) { if (const auto *TD = dyn_cast(D)) { switch (TD->getTagKind()) { case TTK_Interface: // fall through + case TTK_Interface_bsc: case TTK_Struct: return CXCursor_StructDecl; case TTK_Class: @@ -5376,6 +5379,7 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { case DeclSpec::TST_struct: case DeclSpec::TST_class: case DeclSpec::TST_interface: + case DeclSpec::TST_interface_bsc: Filter = &ResultBuilder::IsClassOrStruct; ContextKind = CodeCompletionContext::CCC_ClassOrStructTag; break; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index dc80bde5f638..69dda8d50e9a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -616,6 +616,7 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { switch (TD->getTagKind()) { case TTK_Struct: return DeclSpec::TST_struct; case TTK_Interface: return DeclSpec::TST_interface; + case TTK_Interface_bsc: return DeclSpec::TST_interface_bsc; case TTK_Union: return DeclSpec::TST_union; case TTK_Class: return DeclSpec::TST_class; case TTK_Enum: return DeclSpec::TST_enum; @@ -810,6 +811,10 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result, FixItTagName = "__interface "; break; + case TTK_Interface_bsc: + FixItTagName = "interface "; + break; + case TTK_Union: FixItTagName = "union "; break; @@ -15209,6 +15214,7 @@ Sema::NonTagKind Sema::getNonTagTypeDeclKind(const Decl *PrevDecl, else if (isa(PrevDecl)) return NTK_TemplateTemplateArgument; switch (TTK) { + case TTK_Interface_bsc: case TTK_Struct: case TTK_Interface: case TTK_Class: @@ -16180,9 +16186,15 @@ CreateNewDecl: if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit())) StdBadAlloc = cast(New); - } else - New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, - cast_or_null(PrevDecl)); + } else{ + if (Kind == TTK_Interface_bsc) { + New = InterfaceDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, + cast_or_null(PrevDecl)); + } + else {New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, + cast_or_null(PrevDecl));} + } + } // C++11 [dcl.type]p3: @@ -16590,7 +16602,7 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, /// to create a FieldDecl object for it. Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth) { - FieldDecl *Res = HandleField(S, cast_or_null(TagD), + FieldDecl *Res = HandleField(S, cast_or_null(TagD), DeclStart, D, static_cast(BitfieldWidth), /*InitStyle=*/ICIS_NoInit, AS_public); return Res; @@ -16598,7 +16610,7 @@ Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, /// HandleField - Analyze a field of a C struct or a C++ data member. /// -FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, +FieldDecl *Sema::HandleField(Scope *S, TagDecl *Record, SourceLocation DeclStart, Declarator &D, Expr *BitWidth, InClassInitStyle InitStyle, @@ -16705,7 +16717,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, /// \todo The Declarator argument is a hack. It will be removed once FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, TypeSourceInfo *TInfo, - RecordDecl *Record, SourceLocation Loc, + TagDecl *Record, SourceLocation Loc, bool Mutable, Expr *BitWidth, InClassInitStyle InitStyle, SourceLocation TSSL, @@ -16789,8 +16801,12 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, BitWidth = nullptr; // If this is declared as a bit-field, check the bit-field. if (BitWidth) { - BitWidth = VerifyBitField(Loc, II, T, Record->isMsStruct(Context), BitWidth, + if (Record->isInterfaceBSC()) { + BitWidth = VerifyBitField(Loc, II, T, cast(Record)->isMsStruct(Context), BitWidth, + &ZeroWidth).get();} else{ + BitWidth = VerifyBitField(Loc, II, T, cast(Record)->isMsStruct(Context), BitWidth, &ZeroWidth).get(); + } if (!BitWidth) { InvalidDecl = true; BitWidth = nullptr; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8843c1f8d082..6d029d7cc6c3 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4346,6 +4346,7 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, case Type::ConstantMatrix: case Type::Record: case Type::Enum: + case Type::Interface: case Type::Elaborated: case Type::TemplateSpecialization: case Type::ObjCObject: diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index f9b5e7dc2a6c..5814d1d9a8f5 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -2820,6 +2820,9 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { case Type::Builtin: break; + case Type::Interface: + break; + // -- If T is a class type (including unions), its associated // classes are: the class itself; the class of which it is // a member, if any; and its direct and indirect base classes. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 12880b95b9c6..a24329698779 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -6063,6 +6063,10 @@ bool UnnamedLocalNoLinkageFinder::VisitEnumType(const EnumType* T) { return VisitTagDecl(T->getDecl()); } +bool UnnamedLocalNoLinkageFinder::VisitInterfaceType(const InterfaceType* T) { + return VisitTagDecl(T->getDecl()); +} + bool UnnamedLocalNoLinkageFinder::VisitTemplateTypeParmType( const TemplateTypeParmType*) { return false; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index ee4316e7a632..8a340c809332 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1631,6 +1631,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, case Type::FunctionNoProto: case Type::Record: case Type::Enum: + case Type::Interface: case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: @@ -6074,6 +6075,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, case Type::FunctionNoProto: case Type::Record: case Type::Enum: + case Type::Interface: case Type::ObjCInterface: case Type::ObjCObject: case Type::ObjCObjectPointer: diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 5cbb2039bf00..f5e75cd8426a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3513,6 +3513,10 @@ Decl *TemplateDeclInstantiator::VisitRecordDecl(RecordDecl *D) { llvm_unreachable("There are only CXXRecordDecls in C++"); } +Decl *TemplateDeclInstantiator::VisitInterfaceDecl(InterfaceDecl *D) { + llvm_unreachable("There are only CXXRecordDecls in C++"); +} + Decl * TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *D) { diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 1951aec3d17d..d6f5fedd082f 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -901,6 +901,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_union: case TST_struct: case TST_interface: + case TST_interface_bsc: case TST_class: case TST_auto: case TST_auto_type: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 75e8e350bd48..de471eec734a 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1573,6 +1573,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state, case DeclSpec::TST_enum: case DeclSpec::TST_union: case DeclSpec::TST_struct: + case DeclSpec::TST_interface_bsc: case DeclSpec::TST_interface: { TagDecl *D = dyn_cast_or_null(DS.getRepAsDecl()); if (!D) { @@ -3417,6 +3418,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, } else { switch (cast(SemaRef.CurContext)->getTagKind()) { case TTK_Enum: llvm_unreachable("unhandled tag kind"); + case TTK_Interface_bsc: case TTK_Struct: Error = Cxx ? 1 : 2; /* Struct member */ break; case TTK_Union: Error = Cxx ? 3 : 4; /* Union member */ break; case TTK_Class: Error = 5; /* Class member */ break; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3c68f9458e58..80142101b84b 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -949,6 +949,10 @@ public: return SemaRef.Context.getTypeDeclType(Record); } + QualType RebuildInterfaceType(InterfaceDecl *Interface) { + return SemaRef.Context.getTypeDeclType(Interface); + } + /// Build a new Enum type. QualType RebuildEnumType(EnumDecl *Enum) { return SemaRef.Context.getTypeDeclType(Enum); @@ -6155,6 +6159,30 @@ QualType TreeTransform::TransformRecordType(TypeLocBuilder &TLB, return Result; } +template +QualType TreeTransform::TransformInterfaceType(TypeLocBuilder &TLB, + InterfaceTypeLoc TL) { + const InterfaceType *T = TL.getTypePtr(); + InterfaceDecl *Interface + = cast_or_null(getDerived().TransformDecl(TL.getNameLoc(), + T->getDecl())); + if (!Interface) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Interface != T->getDecl()) { + Result = getDerived().RebuildInterfaceType(Interface); + if (Result.isNull()) + return QualType(); + } + + InterfaceTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; +} + template QualType TreeTransform::TransformEnumType(TypeLocBuilder &TLB, EnumTypeLoc TL) { diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index feb841833f9f..9af49a3e608a 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -350,6 +350,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::TypeAlias: case Decl::Enum: case Decl::Record: + case Decl::Interface: case Decl::CXXRecord: case Decl::ClassTemplateSpecialization: case Decl::ClassTemplatePartialSpecialization: diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 1f68f6bc3e38..25eaff4fba49 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6678,6 +6678,10 @@ void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) { TL.setNameLoc(readSourceLocation()); } +void TypeLocReader::VisitInterfaceTypeLoc(InterfaceTypeLoc TL) { + TL.setNameLoc(readSourceLocation()); +} + void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) { TL.setAttr(ReadAttr()); } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index e2dc84e848f5..805c47267c21 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -331,7 +331,9 @@ namespace clang { RedeclarableResult VisitTagDecl(TagDecl *TD); void VisitEnumDecl(EnumDecl *ED); RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD); + RedeclarableResult VisitInterfaceDeclImpl(InterfaceDecl *RD); void VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); } + void VisitInterfaceDecl(InterfaceDecl *RD) {VisitInterfaceDeclImpl(RD);} RedeclarableResult VisitCXXRecordDeclImpl(CXXRecordDecl *D); void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); } RedeclarableResult VisitClassTemplateSpecializationDeclImpl( @@ -807,6 +809,24 @@ ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { return Redecl; } +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitInterfaceDeclImpl(InterfaceDecl *RD) { + RedeclarableResult Redecl = VisitTagDecl(RD); + RD->setHasFlexibleArrayMember(Record.readInt()); + RD->setAnonymousStructOrUnion(Record.readInt()); + RD->setHasObjectMember(Record.readInt()); + RD->setHasVolatileMember(Record.readInt()); + RD->setNonTrivialToPrimitiveDefaultInitialize(Record.readInt()); + RD->setNonTrivialToPrimitiveCopy(Record.readInt()); + RD->setNonTrivialToPrimitiveDestroy(Record.readInt()); + RD->setHasNonTrivialToPrimitiveDefaultInitializeCUnion(Record.readInt()); + RD->setHasNonTrivialToPrimitiveDestructCUnion(Record.readInt()); + RD->setHasNonTrivialToPrimitiveCopyCUnion(Record.readInt()); + RD->setParamDestroyedInCallee(Record.readInt()); + RD->setArgPassingRestrictions((InterfaceDecl::ArgPassingKind)Record.readInt()); + return Redecl; +} + void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { VisitNamedDecl(VD); // For function declarations, defer reading the type in case the function has diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 40900af6f9e0..b4caaa8e2221 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -396,6 +396,10 @@ void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } +void TypeLocWriter::VisitInterfaceTypeLoc(InterfaceTypeLoc TL) { + Record.AddSourceLocation(TL.getNameLoc()); +} + void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) { Record.AddAttr(TL.getAttr()); } diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 0d94e200a00c..d7915ce3f7a5 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1809,6 +1809,7 @@ DEFAULT_TYPELOC_IMPL(FunctionProto, FunctionType) DEFAULT_TYPELOC_IMPL(FunctionNoProto, FunctionType) DEFAULT_TYPELOC_IMPL(Record, TagType) DEFAULT_TYPELOC_IMPL(Enum, TagType) +DEFAULT_TYPELOC_IMPL(Interface, TagType) DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParm, Type) DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParmPack, Type) DEFAULT_TYPELOC_IMPL(Auto, Type) @@ -6438,6 +6439,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) { case Decl::Enum: case Decl::Record: + case Decl::Interface: case Decl::CXXRecord: case Decl::ClassTemplateSpecialization: case Decl::ClassTemplatePartialSpecialization: diff --git a/clang/tools/libclang/CIndexCXX.cpp b/clang/tools/libclang/CIndexCXX.cpp index a06fe7ba4af5..82a35159928f 100644 --- a/clang/tools/libclang/CIndexCXX.cpp +++ b/clang/tools/libclang/CIndexCXX.cpp @@ -64,6 +64,7 @@ enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) { getCursorDecl(C))) { switch (PartialSpec->getTagKind()) { case TTK_Interface: + case TTK_Interface_bsc: case TTK_Struct: return CXCursor_StructDecl; case TTK_Class: return CXCursor_ClassDecl; case TTK_Union: return CXCursor_UnionDecl; -- Gitee From 587acd67ce2844f7b5eca4c2694103dc568c228c Mon Sep 17 00:00:00 2001 From: zhangyi Date: Sat, 25 Feb 2023 15:41:49 +0800 Subject: [PATCH 10/13] [BSC] fix interface function decl make function decl be the member of interface decl now we can parse: interface I { void f(); } the ast is like: --InterfaceDecl I |---functionDecl f --- clang/include/clang/Parse/Parser.h | 7 +- clang/include/clang/Sema/DeclSpec.h | 6 + clang/include/clang/Sema/Sema.h | 4 + clang/lib/Parse/ParseDecl.cpp | 233 ++++++++++++++-------------- clang/lib/Sema/SemaDecl.cpp | 35 ++++- 5 files changed, 161 insertions(+), 124 deletions(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index d1ba07470d65..8194a40bc42c 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2387,8 +2387,8 @@ private: void ParseEnumBody(SourceLocation StartLoc, Decl *TagDecl); void ParseStructUnionBody(SourceLocation StartLoc, DeclSpec::TST TagType, RecordDecl *TagDecl); - void ParseInterfaceBody(SourceLocation StartLoc, DeclSpec::TST TagType, - InterfaceDecl *TagDecl); + void ParseInterfaceBody(SourceLocation StartLoc, SourceLocation AttrFixitLoc, + ParsedAttributesWithRange &Attrs, unsigned TagType, Decl *TagDecl); void ParseStructDeclaration( ParsingDeclSpec &DS, @@ -3041,6 +3041,9 @@ private: LateParsedAttrList &LateAttrs); void MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(Declarator &D, VirtSpecifiers &VS); +DeclGroupPtrTy ParseInterfaceMemberDeclaration(ParsedAttributes &Attr, +const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), + ParsingDeclRAIIObject *DiagsFromTParams = nullptr); DeclGroupPtrTy ParseCXXClassMemberDeclaration( AccessSpecifier AS, ParsedAttributes &Attr, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 3c9bb18397e4..8a656b4d229a 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1891,6 +1891,8 @@ private: /// parameters (if any). TemplateParameterList *InventedTemplateParameterList; + bool IsInterfaceMem; + #ifndef _MSC_VER union { #endif @@ -2233,6 +2235,10 @@ public: Name.setIdentifier(Id, IdLoc); } + bool getIsInterfaceMem() const {return IsInterfaceMem;} + + void setIsInterfaceMem(bool i) {IsInterfaceMem = i;} + /// Set the decomposition bindings for this declarator. void setDecompositionBindings(SourceLocation LSquareLoc, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index a2a429d14279..26e8c4ade9a8 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7078,6 +7078,10 @@ public: /// conditions that are needed for the attribute to have an effect. void checkIllFormedTrivialABIStruct(CXXRecordDecl &RD); + NamedDecl *ActOnInterfaceMemberDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists); + + void ActOnFinishInterfaceMemberSpecification(Decl *TagDecl); void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac, SourceLocation RBrac, diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 3db8a59b0914..a3237763e8b6 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4376,126 +4376,129 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); } -void Parser::ParseInterfaceBody(SourceLocation RecordLoc, - DeclSpec::TST TagType, InterfaceDecl *TagDecl) - { - PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc, - "parsing struct/union body"); - assert(!getLangOpts().CPlusPlus && "C++ declarations not supported"); - - BalancedDelimiterTracker T(*this, tok::l_brace); - if (T.consumeOpen()) - return; - - ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope); - Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); - - // While we still have something to read, read the declarations in the struct. - while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && - Tok.isNot(tok::eof)) { - // Each iteration of this loop reads one struct-declaration. - - // Check for extraneous top-level semicolon. - if (Tok.is(tok::semi)) { - ConsumeExtraSemi(InsideStruct, TagType); - continue; - } - - // Parse _Static_assert declaration. - if (Tok.isOneOf(tok::kw__Static_assert, tok::kw_static_assert)) { - SourceLocation DeclEnd; - ParseStaticAssertDeclaration(DeclEnd); - continue; - } - - if (Tok.is(tok::annot_pragma_pack)) { - HandlePragmaPack(); - continue; - } - - if (Tok.is(tok::annot_pragma_align)) { - HandlePragmaAlign(); - continue; - } - - if (Tok.is(tok::annot_pragma_openmp)) { - // Result can be ignored, because it must be always empty. - AccessSpecifier AS = AS_none; - ParsedAttributesWithRange Attrs(AttrFactory); - (void)ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs); - continue; - } - - if (tok::isPragmaAnnotation(Tok.getKind())) { - Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl) - << DeclSpec::getSpecifierName( - TagType, Actions.getASTContext().getPrintingPolicy()); - ConsumeAnnotationToken(); - continue; +Parser::DeclGroupPtrTy Parser::ParseInterfaceMemberDeclaration(ParsedAttributes &AccessAttrs, const ParsedTemplateInfo &TemplateInfo, +ParsingDeclRAIIObject *TemplateDiags) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + ParsedAttributesWithRange attrs(AttrFactory); + ParsedAttributesViewWithRange FnAttrs; + // we need to keep these attributes for future diagnostic + // before they are taken over by declaration specifier + FnAttrs.addAll(attrs.begin(), attrs.end()); + FnAttrs.Range = attrs.Range; + LateParsedAttrList CommonLateParsedAttrs; + // decl-specifier-seq: + // Parse the common declaration-specifiers piece + ParsingDeclSpec DS(*this, TemplateDiags); + DS.takeAttributesFrom(attrs); + ParseDeclarationSpecifiers(DS, TemplateInfo, AS_public, DeclSpecContext::DSC_class, &CommonLateParsedAttrs); + MultiTemplateParamsArg TemplateParams(TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : nullptr, + TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); + + if (TryConsumeToken(tok::semi)) { + RecordDecl *AnonRecord = nullptr; + Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_public, DS, TemplateParams, false, AnonRecord); + DS.complete(TheDecl); + if (AnonRecord) { + Decl* decls[] = {AnonRecord, TheDecl}; + return Actions.BuildDeclaratorGroup(decls); + } + return Actions.ConvertDeclToDeclGroup(TheDecl); + } + ParsingDeclarator DeclaratorInfo(*this, DS, DeclaratorContext::Member); + if (TemplateInfo.TemplateParams) + DeclaratorInfo.setTemplateParameterLists(TemplateParams); + VirtSpecifiers VS; + //Hold late-parsed attributes so we can attach a Decl to them later. + LateParsedAttrList LateParsedAttrs; + SmallVector DeclsInGroup; + ExprResult BitfieldSize; + ExprResult TrailingRequiresClause; + ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs); + while(1) { + NamedDecl *ThisDecl = Actions.ActOnInterfaceMemberDeclarator( + getCurScope(), DeclaratorInfo, TemplateParams); + if (ThisDecl) { + Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs); + if (!ThisDecl->isInvalidDecl()) { + //Set the Decl for any late parsed attributes + for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) + CommonLateParsedAttrs[i]->addDecl(ThisDecl); + for (unsigned i = 0, ni = LateParsedAttrs.size(); i< ni; ++i) + LateParsedAttrs[i]->addDecl(ThisDecl); } - - if (!Tok.is(tok::at)) { - auto CFieldCallback = [&](ParsingFieldDeclarator &FD) { - // Install the declarator into the current TagDecl. - Decl *Field = - Actions.ActOnField(getCurScope(), TagDecl, - FD.D.getDeclSpec().getSourceRange().getBegin(), - FD.D, FD.BitfieldSize); - FD.complete(Field); - }; - - // Parse all the comma separated declarators. - ParsingDeclSpec DS(*this); - ParseStructDeclaration(DS, CFieldCallback); - } else { // Handle @defs - ConsumeToken(); - if (!Tok.isObjCAtKeyword(tok::objc_defs)) { - Diag(Tok, diag::err_unexpected_at); - SkipUntil(tok::semi); - continue; - } - ConsumeToken(); - ExpectAndConsume(tok::l_paren); - if (!Tok.is(tok::identifier)) { - Diag(Tok, diag::err_expected) << tok::identifier; - SkipUntil(tok::semi); - continue; + Actions.FinalizeDeclaration(ThisDecl); + DeclsInGroup.push_back(ThisDecl); //Put each Decl inside struct Foo + if (DeclaratorInfo.isFunctionDeclarator() && + DeclaratorInfo.getDeclSpec().getStorageClassSpec() != + DeclSpec::SCS_typedef) + HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl); + } + LateParsedAttrs.clear(); + DeclaratorInfo.complete(ThisDecl); + // if we dont have a comma, it is either the end of the list (a, ';') + // or an error, bail out + SourceLocation CommaLoc; + if (!TryConsumeToken(tok::comma, CommaLoc)) + break; + if (Tok.isAtStartOfLine() && + !MightBeDeclarator(DeclaratorContext::Member)) { + Diag(CommaLoc, diag::err_expected_semi_declaration) << FixItHint::CreateReplacement(CommaLoc, ";"); + break; } - SmallVector Fields; - Actions.ActOnDefs(getCurScope(), TagDecl, Tok.getLocation(), - Tok.getIdentifierInfo(), Fields); - ConsumeToken(); - ExpectAndConsume(tok::r_paren); - } + // Parse the next declarator + DeclaratorInfo.clear(); + VS.clear(); + BitfieldSize = ExprResult(false); + DeclaratorInfo.setCommaLoc(CommaLoc); + if (ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) + break; + } + return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup); +} - if (TryConsumeToken(tok::semi)) - continue; + - if (Tok.is(tok::r_brace)) { - ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list); - break; +void Parser::ParseInterfaceBody(SourceLocation RecordLoc, SourceLocation AttrFixitLoc, + ParsedAttributesWithRange &Attrs, + unsigned TagType, Decl *TagDecl) { + PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc, + "parsing interface body"); + bool NonNestedClass = true; + // Enter a scope for the class + ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope); + + // Note that we are parsing a new (potentially-nested) class definition + ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass, false); + if (TagDecl) + Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); + if (!Tok.is(tok::l_brace)) { + if (TagDecl) + Actions.ActOnTagDefinitionError(getCurScope(), TagDecl); + return; + } + BalancedDelimiterTracker T(*this, tok::l_brace); + T.consumeOpen(); + ParsedAttributesWithRange AccessAttrs(AttrFactory); + if (TagDecl) { + // While we still have something to read. read the member-decls + while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { + // Each iter of this loop reads one member-declaration + ParseInterfaceMemberDeclaration(AccessAttrs); + MaybeDestroyTemplateIds(); } - - ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list); - // Skip to end of block or statement to avoid ext-warning on extra ';'. - SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); - // If we stopped at a ';', eat it. - TryConsumeToken(tok::semi); + T.consumeClose(); + } else { + SkipUntil(tok::r_brace); } - - T.consumeClose(); - ParsedAttributes attrs(AttrFactory); - // If attributes exist after struct contents, parse them. - MaybeParseGNUAttributes(attrs); - - SmallVector FieldDecls(TagDecl->field_begin(), - TagDecl->field_end()); - - Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls, - T.getOpenLocation(), T.getCloseLocation(), attrs); - StructScope.Exit(); - Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); + if (TagDecl) { + Actions.ActOnFinishInterfaceMemberSpecification(TagDecl);} + if (TagDecl) { + Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); + } + // Leave the class scope + ParsingDef.Pop(); + ClassScope.Exit(); } /// ParseEnumSpecifier /// enum-specifier: [C99 6.7.2.2] @@ -5405,10 +5408,8 @@ void Parser::ParseInterfaceSpecifier(tok::TokenKind TagTokKind, ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType, TagOrTempResult.get()); else { - Decl *D = - SkipBody.CheckSameAsPrevious ? SkipBody.New : TagOrTempResult.get(); // Parse the definition body. - ParseInterfaceBody(StartLoc, TagType, cast(D)); + ParseInterfaceBody(StartLoc, AttrFixitLoc, attrs, TagType, TagOrTempResult.get()); if (SkipBody.CheckSameAsPrevious && !Actions.ActOnDuplicateDefinition(DS, TagOrTempResult.get(), SkipBody)) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 69dda8d50e9a..438bcdff5b04 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6680,7 +6680,7 @@ static bool shouldConsiderLinkage(const VarDecl *VD) { return false; if (isa(DC)) return false; - llvm_unreachable("Unexpected context"); + return false; } static bool shouldConsiderLinkage(const FunctionDecl *FD) { @@ -6690,6 +6690,8 @@ static bool shouldConsiderLinkage(const FunctionDecl *FD) { return true; if (DC->isRecord()) return false; + if (DC->isInterface()) + return false; llvm_unreachable("Unexpected context"); } @@ -8899,6 +8901,13 @@ static Scope *getTagInjectionScope(Scope *S, const LangOptions &LangOpts) { return S; } +NamedDecl *Sema::ActOnInterfaceMemberDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists) { + D.setIsInterfaceMem(true); + NamedDecl *Member = HandleDeclarator(S, D, TemplateParameterLists); + return Member; +} + NamedDecl* Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, @@ -8931,10 +8940,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, diag::err_invalid_thread) << DeclSpec::getSpecifierName(TSCS); - if (D.isFirstDeclarationOfMember()) - adjustMemberFunctionCC(R, D.isStaticMember(), D.isCtorOrDtor(), - D.getIdentifierLoc()); - + if (D.isFirstDeclarationOfMember()) { + if (D.getIsInterfaceMem()) { + adjustMemberFunctionCC(R, true, D.isCtorOrDtor(), + D.getIdentifierLoc()); // TODO: add bsc's abi + } else {adjustMemberFunctionCC(R, D.isStaticMember(), D.isCtorOrDtor(), + D.getIdentifierLoc());} + + } bool isFriend = false; FunctionTemplateDecl *FunctionTemplate = nullptr; bool isMemberSpecialization = false; @@ -16435,6 +16448,12 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, "Broken injected-class-name"); } +void Sema::ActOnFinishInterfaceMemberSpecification(Decl *TagDecl) { + if (!TagDecl) + return; + AdjustDeclIfTemplate(TagDecl); +} + void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, SourceRange BraceRange) { AdjustDeclIfTemplate(TagD); @@ -16443,9 +16462,13 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, // Make sure we "complete" the definition even it is invalid. if (Tag->isBeingDefined()) { - assert(Tag->isInvalidDecl() && "We should already have completed it"); + // assert(Tag->isInvalidDecl() && "We should already have completed it"); if (RecordDecl *RD = dyn_cast(Tag)) RD->completeDefinition(); + if (InterfaceDecl *ID = dyn_cast(Tag)) + + ID->completeDefinition(); + llvm::outs() << "~~~~~~~~~~~" << "\n"; } if (isa(Tag)) { -- Gitee From 4b8f55aefde67e1ac10596b8bbb63e634f27eca2 Mon Sep 17 00:00:00 2001 From: zhangyi Date: Mon, 27 Feb 2023 10:15:00 +0800 Subject: [PATCH 11/13] [BSC] add check invalid var decl --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaDecl.cpp | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 80600c146673..65828b1442f0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2993,6 +2993,8 @@ def err_attribute_not_clinkage : Error< "function type with %0 attribute must have C linkage">; def err_function_decl_cmse_ns_call : Error< "functions may not be declared with 'cmse_nonsecure_call' attribute">; +def err_interface_member_not_func : Error< + "only function declarations can be interface member !">; def err_attribute_address_function_type : Error< "function type may not be qualified with an address space">; def err_as_qualified_auto_decl : Error< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 438bcdff5b04..192675e4f0ad 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5897,6 +5897,11 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, TemplateParamLists, AddToScope); } else { + if (D.getIsInterfaceMem()) { + Diag(D.getIdentifierLoc(), diag::err_interface_member_not_func); + D.setInvalidType(true); + //return nullptr; + } New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, TemplateParamLists, AddToScope); } @@ -16466,9 +16471,7 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, if (RecordDecl *RD = dyn_cast(Tag)) RD->completeDefinition(); if (InterfaceDecl *ID = dyn_cast(Tag)) - ID->completeDefinition(); - llvm::outs() << "~~~~~~~~~~~" << "\n"; } if (isa(Tag)) { -- Gitee From 0ae64b946d5f5c8935b04a15485b61447210a63a Mon Sep 17 00:00:00 2001 From: zhangyi Date: Wed, 1 Mar 2023 17:26:47 +0800 Subject: [PATCH 12/13] [BSC] add "This" type(not finished) only backup for merging branch code --- clang/include/clang/AST/ASTContext.h | 1 + clang/include/clang/Basic/Specifiers.h | 1 + clang/include/clang/Basic/TokenKinds.def | 2 +- clang/include/clang/Sema/DeclSpec.h | 1 + clang/lib/Lex/Lexer.cpp | 14 ++++++++++---- clang/lib/Parse/ParseDecl.cpp | 4 ++++ clang/lib/Sema/SemaTemplateVariadic.cpp | 1 + clang/lib/Sema/SemaType.cpp | 3 +++ 8 files changed, 22 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index aae2b50bf9dc..03e2ecd8fad3 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -981,6 +981,7 @@ public: CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99. CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99. CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; + CanQualType ThisTy; CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; CanQualType UnsignedLongLongTy, UnsignedInt128Ty; CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty; diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index af993becea38..3524d8ab5fe1 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -79,6 +79,7 @@ namespace clang { TST_unknown_anytype, // __unknown_anytype extension TST_atomic, // C11 _Atomic TST_interface_bsc, + TST_This, #define GENERIC_IMAGE_TYPE(ImgType, Id) TST_##ImgType##_t, // OpenCL image types #include "clang/Basic/OpenCLImageTypes.def" TST_error // erroneous type diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 8b8e30e56fd8..cb9d6ef0f92e 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -330,7 +330,7 @@ KEYWORD(__objc_no , KEYALL) KEYWORD(interface , KEYALL) KEYWORD(implements , KEYALL) - +KEYWORD(This , KEYALL) // C++ 2.11p1: Keywords. KEYWORD(asm , KEYCXX|KEYGNU) diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 8a656b4d229a..8f88c46c36c6 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -296,6 +296,7 @@ public: static const TST TST_unknown_anytype = clang::TST_unknown_anytype; static const TST TST_atomic = clang::TST_atomic; static const TST TST_interface_bsc = clang::TST_interface_bsc; + static const TST TST_This = clang::TST_This; #define GENERIC_IMAGE_TYPE(ImgType, Id) \ static const TST TST_##ImgType##_t = clang::TST_##ImgType##_t; #include "clang/Basic/OpenCLImageTypes.def" diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 5dc4fd58416a..2e4df187e1f2 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -3226,16 +3226,22 @@ LexNextToken: unsigned SizeTmp, SizeTmp2; // Temporaries for use in cases below. if (*CurPtr == 's' && *(CurPtr+1) == 't'){ - llvm::outs() << "xxxxxxxx" << "\n"; + llvm::outs() << "xxxxxxxx1" << "\n"; } if (*CurPtr == 'e' && *(CurPtr+1) == 'n'){ - llvm::outs() << "xxxxxxxx" << "\n"; + llvm::outs() << "xxxxxxxx2" << "\n"; } if (*CurPtr == 'c' && *(CurPtr+1) == 'l'){ - llvm::outs() << "xxxxxxxx" << "\n"; + llvm::outs() << "xxxxxxxx3" << "\n"; } if (*CurPtr == 'i' && *(CurPtr+1) == 'n' && *(CurPtr+2) == 't' && *(CurPtr+3) == 'e'){ - llvm::outs() << "xxxxxxxx" << "\n"; + llvm::outs() << "xxxxxxxx4" << "\n"; + } + if (*CurPtr == 'T' && *(CurPtr+1) == 'h' && *(CurPtr+2) == 'i' && *(CurPtr+3) == 's'){ + llvm::outs() << "xxxxxxxx5" << "\n"; + } + if (*CurPtr == 'i' && *(CurPtr+1) == 'n' && *(CurPtr+2) == 't'){ + llvm::outs() << "xxxxxxxx6" << "\n"; } // Read a character, advancing over it. char Char = getAndAdvanceChar(CurPtr, Result); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index a3237763e8b6..ca44e7c81df7 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3801,6 +3801,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw_This: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_This, Loc, PrevSpec, + DiagID, Policy); + break; case tok::kw__ExtInt: { ExprResult ER = ParseExtIntegerArgument(); if (ER.isInvalid()) diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index d6f5fedd082f..d3212ec530e2 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -879,6 +879,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_unspecified: case TST_void: + case TST_This: case TST_char: case TST_wchar: case TST_char8: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index de471eec734a..fe481466e1ef 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1345,6 +1345,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state, "Unknown TSS value"); Result = Context.Char32Ty; break; + case DeclSpec::TST_This: + Result = Context.ThisTy; + break; case DeclSpec::TST_unspecified: // If this is a missing declspec in a block literal return context, then it // is inferred from the return statements inside the block. -- Gitee From f3335c158b6f1938c8345a7c8f1e9d57d8b9c5e5 Mon Sep 17 00:00:00 2001 From: zhangyi Date: Tue, 7 Mar 2023 09:58:20 +0800 Subject: [PATCH 13/13] [BSC] add initial support for ThisType avoid check in SemaDecl ActOnParamDeclarator, now we return a new Decl(empty) directly when we saw the 'This' type. --- clang/include/clang/AST/ASTContext.h | 3 +++ clang/include/clang/AST/BuiltinTypes.def | 2 ++ clang/include/clang/AST/RecursiveASTVisitor.h | 5 +++- clang/include/clang/AST/Type.h | 23 +++++++++++++++++ clang/include/clang/AST/TypeLoc.h | 8 ++++++ clang/include/clang/AST/TypeProperties.td | 8 ++++++ clang/include/clang/Basic/TokenKinds.def | 1 - clang/include/clang/Basic/TypeNodes.td | 1 + clang/include/clang/Lex/Token.h | 11 ++++++++ clang/include/clang/Sema/DeclSpec.h | 2 +- .../include/clang/Serialization/ASTBitCodes.h | 2 ++ clang/lib/AST/ASTContext.cpp | 25 +++++++++++++++++++ clang/lib/AST/ASTImporter.cpp | 10 ++++++++ clang/lib/AST/ItaniumMangle.cpp | 4 +++ clang/lib/AST/MicrosoftMangle.cpp | 5 ++++ clang/lib/AST/ODRHash.cpp | 4 +++ clang/lib/AST/TypePrinter.cpp | 7 ++++++ clang/lib/Lex/Lexer.cpp | 22 +++------------- clang/lib/Parse/ParseDecl.cpp | 10 +++++--- clang/lib/Sema/DeclSpec.cpp | 4 ++- clang/lib/Sema/SemaDecl.cpp | 9 ++++--- clang/lib/Sema/SemaTemplate.cpp | 4 +++ clang/lib/Sema/SemaType.cpp | 13 +++++++--- clang/lib/Sema/TreeTransform.h | 7 ++++++ clang/lib/Serialization/ASTCommon.cpp | 4 +-- clang/lib/Serialization/ASTReader.cpp | 4 +++ clang/lib/Serialization/ASTWriter.cpp | 4 +++ clang/tools/libclang/CIndex.cpp | 4 +++ 28 files changed, 171 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 03e2ecd8fad3..d6b5c968a354 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -192,6 +192,7 @@ class ASTContext : public RefCountedBase { mutable llvm::FoldingSet ComplexTypes; mutable llvm::FoldingSet PointerTypes; mutable llvm::FoldingSet AdjustedTypes; + mutable llvm::FoldingSet ThisTypes; mutable llvm::FoldingSet BlockPointerTypes; mutable llvm::FoldingSet LValueReferenceTypes; mutable llvm::FoldingSet RValueReferenceTypes; @@ -1222,6 +1223,8 @@ public: getAdjustedType((QualType)Orig, (QualType)New)); } + QualType getThisType(QualType T) const; + /// Return the uniqued reference to the decayed version of the given /// type. Can only be called on array and function types which decay to /// pointer types. diff --git a/clang/include/clang/AST/BuiltinTypes.def b/clang/include/clang/AST/BuiltinTypes.def index 039765dfdfea..c02ff239601d 100644 --- a/clang/include/clang/AST/BuiltinTypes.def +++ b/clang/include/clang/AST/BuiltinTypes.def @@ -74,6 +74,8 @@ SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(WChar_U, WCharTy)) // 'char8_t' in C++20 (proposed) UNSIGNED_TYPE(Char8, Char8Ty) +UNSIGNED_TYPE(This, ThisTy) + // 'char16_t' in C++ UNSIGNED_TYPE(Char16, Char16Ty) diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index e8405e418176..aac16cba7d55 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -883,6 +883,7 @@ RecursiveASTVisitor::TraverseLambdaCapture(LambdaExpr *LE, } DEF_TRAVERSE_TYPE(BuiltinType, {}) +DEF_TRAVERSE_TYPE(ThisType, {}) DEF_TRAVERSE_TYPE(ComplexType, { TRY_TO(TraverseType(T->getElementType())); }) @@ -1086,7 +1087,7 @@ DEF_TRAVERSE_TYPE(DependentExtIntType, bool RecursiveASTVisitor::Traverse##TYPE##Loc(TYPE##Loc TL) { \ if (!getDerived().shouldTraversePostOrder()) { \ TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ - if (getDerived().shouldWalkTypesOfTypeLocs()) \ + if (getDerived().shouldWalkTypesOfTypeLocs()) \ TRY_TO(WalkUpFrom##TYPE(const_cast(TL.getTypePtr()))); \ } \ { CODE; } \ @@ -1121,6 +1122,7 @@ RecursiveASTVisitor::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) { DEF_TRAVERSE_TYPELOC(BuiltinType, {}) + // FIXME: ComplexTypeLoc is unfinished DEF_TRAVERSE_TYPELOC(ComplexType, { TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); @@ -1250,6 +1252,7 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, { DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) DEF_TRAVERSE_TYPELOC(TypedefType, {}) +DEF_TRAVERSE_TYPELOC(ThisType, {}) DEF_TRAVERSE_TYPELOC(TypeOfExprType, { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); }) diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index e254496337a1..1110de1f33fb 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1563,6 +1563,10 @@ protected: unsigned Kind : 8; }; + class ThisTypeBitfields { + friend class ThisType; + }; + /// FunctionTypeBitfields store various bits belonging to FunctionProtoType. /// Only common bits are stored here. Additional uncommon bits are stored /// in a trailing object after FunctionProtoType. @@ -1785,6 +1789,7 @@ protected: AttributedTypeBitfields AttributedTypeBits; AutoTypeBitfields AutoTypeBits; BuiltinTypeBitfields BuiltinTypeBits; + ThisTypeBitfields ThisTypeBits; FunctionTypeBitfields FunctionTypeBits; ObjCObjectTypeBitfields ObjCObjectTypeBits; ReferenceTypeBitfields ReferenceTypeBits; @@ -2476,6 +2481,24 @@ template <> inline const Class##Type *Type::castAs() const { \ } #include "clang/AST/TypeNodes.inc" +class ThisType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + QualType PointeeType; + ThisType(QualType Pointee, QualType CanonType) : + Type(This, CanonType, Pointee->getDependence()), PointeeType(Pointee) {} +public: + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + static bool classof(const Type *T) { return T->getTypeClass() == This; } + QualType getPointeeType() const { return PointeeType; } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) { + ID.AddPointer(Pointee.getAsOpaquePtr()); + } + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getPointeeType()); + } +}; + /// This class is used for builtin types like 'int'. Builtin /// types are always canonical and have a literal name field. class BuiltinType : public Type { diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index ae9d9082efb3..98f48b8b999e 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -666,6 +666,14 @@ public: } }; +class ThisTypeLoc : public InheritingConcreteTypeLoc{ +public: + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + } +}; + /// Wrapper for source info for typedefs. class TypedefTypeLoc : public InheritingConcreteTypeLoc; } +let Class = ThisType in { + def : Property<"pointeeType", QualType> { + let Read = [{ node->getPointeeType() }]; + } + + def : Creator<[{ return ctx.getThisType(pointeeType); }]>; +} + let Class = ReferenceType in { def : Property<"pointeeTypeAsWritten", QualType> { let Read = [{ node->getPointeeTypeAsWritten() }]; diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index cb9d6ef0f92e..7260f6e2e245 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -330,7 +330,6 @@ KEYWORD(__objc_no , KEYALL) KEYWORD(interface , KEYALL) KEYWORD(implements , KEYALL) -KEYWORD(This , KEYALL) // C++ 2.11p1: Keywords. KEYWORD(asm , KEYCXX|KEYGNU) diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td index 2211e474b364..b98af30c7996 100644 --- a/clang/include/clang/Basic/TypeNodes.td +++ b/clang/include/clang/Basic/TypeNodes.td @@ -109,4 +109,5 @@ def ObjCObjectPointerType : TypeNode; def PipeType : TypeNode; def AtomicType : TypeNode; def ExtIntType : TypeNode; +def ThisType : TypeNode; def DependentExtIntType : TypeNode, AlwaysDependent; diff --git a/clang/include/clang/Lex/Token.h b/clang/include/clang/Lex/Token.h index 89042a674fec..d5bb6b01ac0f 100644 --- a/clang/include/clang/Lex/Token.h +++ b/clang/include/clang/Lex/Token.h @@ -67,6 +67,8 @@ class Token { /// Flags - Bits we track about this token, members of the TokenFlags enum. unsigned short Flags; + bool isThis; + public: // Various flags set per token: enum TokenFlags { @@ -174,6 +176,7 @@ public: PtrData = nullptr; UintData = 0; Loc = SourceLocation().getRawEncoding(); + isThis = false; } IdentifierInfo *getIdentifierInfo() const { @@ -247,6 +250,14 @@ public: Flags &= ~Flag; } + void setThis(bool flag) { + isThis = flag; + } + bool getThis() { + return isThis; + } + + /// Return the internal represtation of the flags. /// /// This is only intended for low-level operations such as writing tokens to diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 8f88c46c36c6..f2dc9c932a5f 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -407,7 +407,7 @@ private: static bool isTypeRep(TST T) { return (T == TST_typename || T == TST_typeofType || - T == TST_underlyingType || T == TST_atomic); + T == TST_underlyingType || T == TST_atomic || T == TST_This); } static bool isExprRep(TST T) { return (T == TST_typeofExpr || T == TST_decltype || T == TST_extint); diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index b17f421abccc..7d0b21adf04d 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1201,6 +1201,8 @@ public: /// The internal '__type_pack_element' template. PREDEF_DECL_TYPE_PACK_ELEMENT_ID = 17, + + PREDEF_TYPE_THIS_ID = 18, }; /// The number of declaration IDs that are predefined. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 15e335886901..393022988b00 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1346,6 +1346,8 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, // C++20 (proposed) InitBuiltinType(Char8Ty, BuiltinType::Char8); + if (LangOpts.BSC) + InitBuiltinType(ThisTy, BuiltinType::This); if (LangOpts.CPlusPlus) // C++0x 3.9.1p5, extension for C++ InitBuiltinType(Char16Ty, BuiltinType::Char16); @@ -3177,6 +3179,29 @@ QualType ASTContext::getPointerType(QualType T) const { return QualType(New, 0); } +QualType ASTContext::getThisType(QualType T) const { + llvm::FoldingSetNodeID ID; + ThisType::Profile(ID, T); + + void *InsertPos = nullptr; + if (ThisType *TT = + ThisTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(TT, 0); + QualType Canonical; + if (!T.isCanonical()) { + Canonical = getThisType(getCanonicalType(T)); + + // Get the new insert position for the node we care about. + ThisType *NewIP = + ThisTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; + } + auto *New = new (*this, TypeAlignment) ThisType(T, Canonical); + Types.push_back(New); + ThisTypes.InsertNode(New, InsertPos); + return QualType(New, 0); +} + QualType ASTContext::getAdjustedType(QualType Orig, QualType New) const { llvm::FoldingSetNodeID ID; AdjustedType::Profile(ID, Orig, New); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 54dd43775837..465847fe6af1 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -333,6 +333,7 @@ namespace clang { ExpectedType VisitType(const Type *T); ExpectedType VisitAtomicType(const AtomicType *T); ExpectedType VisitBuiltinType(const BuiltinType *T); + ExpectedType VisitThisType(const ThisType *T); ExpectedType VisitDecayedType(const DecayedType *T); ExpectedType VisitComplexType(const ComplexType *T); ExpectedType VisitPointerType(const PointerType *T); @@ -1102,6 +1103,15 @@ ExpectedType ASTNodeImporter::VisitPointerType(const PointerType *T) { return Importer.getToContext().getPointerType(*ToPointeeTypeOrErr); } +ExpectedType ASTNodeImporter::VisitThisType(const ThisType *T) { + // FIXME: Check for blocks support in "to" context. + ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType()); + if (!ToPointeeTypeOrErr) + return ToPointeeTypeOrErr.takeError(); + + return Importer.getToContext().VoidTy; +} + ExpectedType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) { // FIXME: Check for blocks support in "to" context. ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType()); diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index c4078d369642..e362508d228b 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3221,6 +3221,10 @@ void CXXNameMangler::mangleType(const ComplexType *T) { mangleType(T->getElementType()); } +void CXXNameMangler::mangleType(const ThisType *T) { + return; +} + // ARM's ABI for Neon vector types specifies that they should be mangled as // if they are structs (to match ARM's initial implementation). The // vector type must be one of the special types predefined by ARM. diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 3de90205234b..a04f5c5b4530 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -2943,6 +2943,11 @@ void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T, mangleType(PointeeType, Range); } +void MicrosoftCXXNameMangler::mangleType(const ThisType *T, + Qualifiers Quals, SourceRange Range) { + return; +} + // ::= // ::= $$Q E? // # the E is required for 64-bit non-static rvalue references diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 14415b87c7b3..381cbda1a14a 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -841,6 +841,10 @@ public: VisitType(T); } + void VisitThisType(const ThisType *T) { + VisitType(T); + } + void VisitComplexType(const ComplexType *T) { AddQualType(T->getElementType()); VisitType(T); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 160183bfa887..80c96507f340 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -376,6 +376,13 @@ void TypePrinter::printComplexAfter(const ComplexType *T, raw_ostream &OS) { printAfter(T->getElementType(), OS); } +void TypePrinter::printThisBefore(const ThisType *T, raw_ostream &OS) { + OS << "This "; +} + +void TypePrinter::printThisAfter(const ThisType *T, raw_ostream &OS) { +} + void TypePrinter::printPointerBefore(const PointerType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false); diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 2e4df187e1f2..d1fa83e4e954 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -1642,6 +1642,10 @@ bool Lexer::tryConsumeIdentifierUTF8Char(const char *&CurPtr) { bool Lexer::LexIdentifier(Token &Result, const char *CurPtr) { // Match [_A-Za-z0-9]*, we have already matched [_A-Za-z$] unsigned Size; + Size = 1; + if (*(CurPtr-1) == 'T' && *CurPtr == 'h' && *(CurPtr+1) == 'i' && *(CurPtr+2) == 's'){ + Result.setThis(true); + } unsigned char C = *CurPtr++; while (isIdentifierBody(C)) C = *CurPtr++; @@ -3225,24 +3229,6 @@ LexNextToken: } unsigned SizeTmp, SizeTmp2; // Temporaries for use in cases below. - if (*CurPtr == 's' && *(CurPtr+1) == 't'){ - llvm::outs() << "xxxxxxxx1" << "\n"; - } - if (*CurPtr == 'e' && *(CurPtr+1) == 'n'){ - llvm::outs() << "xxxxxxxx2" << "\n"; - } - if (*CurPtr == 'c' && *(CurPtr+1) == 'l'){ - llvm::outs() << "xxxxxxxx3" << "\n"; - } - if (*CurPtr == 'i' && *(CurPtr+1) == 'n' && *(CurPtr+2) == 't' && *(CurPtr+3) == 'e'){ - llvm::outs() << "xxxxxxxx4" << "\n"; - } - if (*CurPtr == 'T' && *(CurPtr+1) == 'h' && *(CurPtr+2) == 'i' && *(CurPtr+3) == 's'){ - llvm::outs() << "xxxxxxxx5" << "\n"; - } - if (*CurPtr == 'i' && *(CurPtr+1) == 'n' && *(CurPtr+2) == 't'){ - llvm::outs() << "xxxxxxxx6" << "\n"; - } // Read a character, advancing over it. char Char = getAndAdvanceChar(CurPtr, Result); tok::TokenKind Kind; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index ca44e7c81df7..136fdf420c41 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3311,6 +3311,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___super: case tok::kw_decltype: case tok::identifier: { + if (Tok.getThis()) { + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_This, Loc, PrevSpec, + DiagID, Policy); + break; + } // This identifier can only be a typedef name if we haven't already seen // a type-specifier. Without this check we misparse: // typedef int X; struct Y { short X; }; as 'short int'. @@ -3801,10 +3806,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID, Policy); break; - case tok::kw_This: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_This, Loc, PrevSpec, - DiagID, Policy); - break; case tok::kw__ExtInt: { ExprResult ER = ParseExtIntegerArgument(); if (ER.isInvalid()) @@ -4095,6 +4096,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ParseOpenCLQualifiers(DS.getAttributes()); break; + case tok::less: // GCC ObjC supports types like "" as a synonym for // "id". This is hopelessly old fashioned and dangerous, diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 9410511d8102..c1f969341e6e 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -345,6 +345,7 @@ bool Declarator::isDeclarationOfFunction() const { case TST_auto: case TST_auto_type: case TST_bool: + case TST_This: case TST_char: case TST_char8: case TST_char16: @@ -545,6 +546,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, case DeclSpec::TST_unspecified: return "unspecified"; case DeclSpec::TST_void: return "void"; case DeclSpec::TST_char: return "char"; + case DeclSpec::TST_This: return "This"; case DeclSpec::TST_wchar: return Policy.MSWChar ? "__wchar_t" : "wchar_t"; case DeclSpec::TST_char8: return "char8_t"; case DeclSpec::TST_char16: return "char16_t"; @@ -825,7 +827,7 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy) { - assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) && + assert(!isDeclRep(T) && (!isTypeRep(T) || T == TST_This) && !isExprRep(T) && "rep required for these type-spec kinds!"); if (TypeSpecType == TST_error) return false; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 192675e4f0ad..2cc79bfe0a80 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13591,10 +13591,13 @@ 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) { +Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, int ParamSize, const Type *typePtr) { const DeclSpec &DS = D.getDeclSpec(); - + if (DS.getTypeSpecType() == TST_This) { + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + return CheckParameter(Context.getTranslationUnitDecl(), D.getBeginLoc(), + D.getIdentifierLoc(), D.getIdentifier(), TInfo->getType(), TInfo, SC_Register); + } // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. // C++03 [dcl.stc]p2 also permits 'auto'. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index a24329698779..4cd76340cd92 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5928,6 +5928,10 @@ bool UnnamedLocalNoLinkageFinder::VisitBuiltinType(const BuiltinType*) { return false; } +bool UnnamedLocalNoLinkageFinder::VisitThisType(const ThisType*) { + return false; +} + bool UnnamedLocalNoLinkageFinder::VisitComplexType(const ComplexType* T) { return Visit(T->getElementType()); } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index fe481466e1ef..5732fd01536d 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1337,7 +1337,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state, break; case DeclSpec::TST_char16: assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && - "Unknown TSS value"); + "UnknowisNulln TSS value"); Result = Context.Char16Ty; break; case DeclSpec::TST_char32: @@ -1346,7 +1346,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state, Result = Context.Char32Ty; break; case DeclSpec::TST_This: - Result = Context.ThisTy; + Result = S.GetTypeFromParser(DS.getRepAsType()); + assert(!Result.isNull() && "Didn't get a type for typeof?"); + Result = Context.getThisType(Result); break; case DeclSpec::TST_unspecified: // If this is a missing declspec in a block literal return context, then it @@ -1613,7 +1615,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state, if (Result.isNull()) { declarator.setInvalidType(true); } - + // TypeQuals handled by caller. break; } @@ -5947,6 +5949,11 @@ namespace { TL.expandBuiltinRange(DS.getTypeSpecWidthRange()); } } + + void VisitThisTypeLoc(ThisTypeLoc TL) { + return; + } + void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { ElaboratedTypeKeyword Keyword = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType()); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 80142101b84b..80059f252b6d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4812,6 +4812,13 @@ QualType TreeTransform::TransformBuiltinType(TypeLocBuilder &TLB, return T.getType(); } +template +QualType TreeTransform::TransformThisType(TypeLocBuilder &TLB, + ThisTypeLoc T) { + // FIXME: recurse? + return TransformTypeSpecType(TLB, T); +} + template QualType TreeTransform::TransformComplexType(TypeLocBuilder &TLB, ComplexTypeLoc T) { diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index 9af49a3e608a..df65178c2326 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -95,9 +95,7 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { break; case BuiltinType::Accum: ID = PREDEF_TYPE_ACCUM_ID; - break; - case BuiltinType::LongAccum: - ID = PREDEF_TYPE_LONG_ACCUM_ID; + break;PREDEF_TYPE_NULL_ID; break; case BuiltinType::UShortAccum: ID = PREDEF_TYPE_USHORT_ACCUM_ID; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 25eaff4fba49..b4197b75c4d0 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6495,6 +6495,10 @@ void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { } } +void TypeLocReader::VisitThisTypeLoc(ThisTypeLoc TL) { + return; +} + void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) { TL.setNameLoc(readSourceLocation()); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index b4caaa8e2221..4c1f0e804165 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -204,6 +204,10 @@ void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { } } +void TypeLocWriter::VisitThisTypeLoc(ThisTypeLoc TL) { + return; +} + void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index d7915ce3f7a5..5aa3d21c4b37 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1597,6 +1597,10 @@ bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU)); } +bool CursorVisitor::VisitThisTypeLoc(ThisTypeLoc TL) { + return true; +} + bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { return Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)); } -- Gitee