diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index d24f00694f7f7aff3068b913cbc0b2557acc6067..359f666c7f49e8c43814c27f328a2a523b2b2276 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/Decl.h b/clang/include/clang/AST/Decl.h index 1e54e91736a3171cb5b838f9625bc1007af6ed74..254e050b77772147a8403e7952c937675fdce433 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 5da1097e8a7a0ad208fc8cda5fdd813a7a6c3c45..58ba43559e0ef5170366de6aefd5eb2a4ac32f15 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; - } - 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; } + void setExtendedType(QualType ExtendedType) { + this->ExtendedType = ExtendedType; + } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -1967,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/AST/Expr.h b/clang/include/clang/AST/Expr.h index a44d06967431ad0c366a5f2e2db62e468511477a..b19f98326eeba639d34e741d20bb446fd170ed0d 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/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 0ed80a481e78d5692f44182939b8fc2b82649d91..81aed6408fb5a9ac9d1866dcaa9d258e8a13d561 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/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b24dac80502f8090809f6597c84c4559d097d1c0..80600c1466738ea57f89a594fbe7fde7b49d6c70 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/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index ad9bb0a6b91fc6d1f11b1c95ac298f56eed142c8..3f6dc67f257ca42f0e04c748c878702348fe26c7 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. /// @@ -1789,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, @@ -2356,8 +2361,9 @@ 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 IsBSCMethodAmbiguous(); bool DiagnoseMissingSemiAfterTagDefinition( DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext, LateParsedAttrList *LateAttrs = nullptr); @@ -2921,11 +2927,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 e02815bfe54cd04d03496cc8d9931a8ebb93e66d..7f8040d78b90337143160ecfe58f2d9e0c13bb4e 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 11c359717ff8d799e7e680e0ea0495da435d5d23..f57c94ff35a399cb927af476122b2abcf1bf9cd2 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; @@ -1928,18 +1928,20 @@ 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; } - /// 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 d9c17632731733b729a8aeb239b52df7c8b32b4f..b0c085d98044b77808356f310b5929507566a163 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2671,12 +2671,13 @@ 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); 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); @@ -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, @@ -11313,7 +11315,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 880412cd37258829b9c9a2ebe2341b5cf3339608..8c3fc70d26be46a62b11ef21f262d3ae76839982 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 36c0d620b4732d89c016a3d4534e58fbdb56c377..80b9be706ac4293a730faa23593a66e66774b8f6 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; } @@ -3341,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/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 1386504b436d323f9b24d918f21e528823bad827..ec71d0fabe908b6ea20a2b157d405930dd3e9c82 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/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp index 3282fcbd584f3f30809e62fdd723f05af458236d..3e4a497aef988727f8f87e140d27b52f0a984a8b 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/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 03f75ca2d0e249e3c8c7f397abc5ffbb6534d30a..8d4235cc2ec25b0bf2de19beb43446bb49173d42 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/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 20b40259a8c8a59a1a947ebc41d0b5602c7d5bbc..d9c892251ce7035fd665fb8f76efcdf47fe3202d 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->setHasThisParam(D.hasThisParam); + MD->setExtendedType(D.getExtendedType()); + MD->setHasThisParam(D.HasThisParam); } - } + } return Actions.ConvertDeclToDeclGroup(TheDecl); } @@ -2043,15 +2043,17 @@ 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); if (FirstDecl) { - if (auto FD = dyn_cast(FirstDecl)) - FD->setHasThisParam(D.hasThisParam); + if (auto FD = dyn_cast(FirstDecl)) { + FD->setHasThisParam(D.HasThisParam); + FD->setExtendedType(D.getExtendedType()); + } DeclsInGroup.push_back(FirstDecl); - } + } bool ExpectSemi = Context != DeclaratorContext::ForInit; @@ -2965,10 +2967,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); + DeclSpecContext::DSC_normal, nullptr, + BSCScopeSpecFlag); } /// ParseDeclarationSpecifiers @@ -3003,7 +3005,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 +3024,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 +3047,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, SourceLocation Loc = Tok.getLocation(); + 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: DoneWithDeclSpec: @@ -3121,6 +3127,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(); @@ -5664,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++ @@ -5695,13 +5724,13 @@ 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); D.setBSCScopeSpec(&BSS); - Actions.ConvertBSCScopeSpecToType(D, BSS.getBeginLoc()); + Actions.ConvertBSCScopeSpecToType(D, BSS.getBeginLoc(), true); (this->*DirectDeclParser)(D); return; } @@ -6537,20 +6566,20 @@ 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); - } - 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); - if (PD && D.getBSCScopeSpec()) - D.hasThisParam = PD->isThisParam; + ParmVarDecl *PD = + dyn_cast_or_null(ParamInfo.data()[0].Param); + if (PD && !D.getExtendedType().isNull()) + D.HasThisParam = PD->IsThisParam; } HasProto = ParamInfo.size() || getLangOpts().CPlusPlus || getLangOpts().OpenCL; @@ -6799,11 +6828,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 +6950,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/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 6acf76d713fde1a915505357463f6a8103cb914d..6fb1a7dba79a080a9795a938745fc977705cd2f0 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 35d3b4b718db89e4234333bfe00f221d9f928ffc..0170003db76ece0f85ebd768bb2f861b364f98a1 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/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 2a42f058b8ec452edad0a8b0167744c61023c39c..815d078f0c79371e84e7f8e41c261036912f386c 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/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 23c28150ae246d8063314cb5540b86a52765a7c7..dc80bde5f6381434af97a8b508dce9f566a139a3 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()) @@ -3675,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(); @@ -5764,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); @@ -8449,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(); @@ -8458,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 = @@ -13564,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'. @@ -13609,18 +13614,25 @@ 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 is nullptr, it is not a BSCMethod + if (TypePtr && 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(); + << parmDeclType.getAsString(); } - isThisParam = true; + IsThisParam = true; } else { Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name) - << GetNameForDeclarator(D).getName(); + << GetNameForDeclarator(D).getName(); } } @@ -13653,7 +13665,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/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 27d3901d3d0f1c8038bef2489361756704ce25c7..8843c1f8d082d90ac3d647d46ec47d36604909db 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); } @@ -3411,19 +3411,24 @@ 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; 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,7 +5785,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, : (IsExecConfig ? 3 /* kernel function (exec config) */ : 0 /* function */); bool isBSCInstanceFunc = false; - if (FDecl) { + if (FDecl && !Fn->HasBSCScopeSpce) { BSCMethodDecl* MD = dyn_cast_or_null(FDecl); if (MD && MD->getHasThisParam()) { isBSCInstanceFunc = true; @@ -5872,7 +5877,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 +5894,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); @@ -6605,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); @@ -6646,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/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 7c11569ddbdc3838e9d9657879046ddb9c3711b7..30a7a22583837df1dd0bfc0fc9893c195a52fc21 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,18 +1227,33 @@ 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; 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, MemberNameInfo, type, valueKind, OK_Ordinary); } - + assert(!isa(MemberDecl) && "member function not C++ method?"); if (EnumConstantDecl *Enum = dyn_cast(MemberDecl)) { @@ -1416,37 +1430,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 2a5206ca6a974de9d0a6cf8d98d47478715a8cbb..f9b5e7dc2a6c899594a3803824a9340ded35b8b8 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 @@ -2406,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. @@ -2436,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/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index a9a77cca36a02b9297134d95c5514659f75b2289..5cbb2039bf0032a36e4e950941e170c536b606ea 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 c5dd268dd134d31cbcc6ff7bd18d7ae7a423c074..75e8e350bd48dd209b201e03006ed34163325fb7 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(); @@ -1835,7 +1837,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state, bool BSCMethod 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); @@ -1843,25 +1846,32 @@ 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(); + 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; } } } + return T; } static std::string getPrintableNameForEntity(DeclarationName Entity) { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 91ec268465daaa032dba6470f4c641e179552df7..e2dc84e848f5c9ed429377e31ef843c9ce982d0a 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 ca8d5fd323ea2c0b61950787444266212de06081..70f5002fd9d7d5d9e2864ddc98d59c1ecafc8954 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1368,16 +1368,14 @@ 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() && - !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(); @@ -2283,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 @@ -2302,48 +2300,50 @@ 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. // // 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 diff --git a/clang/test/BSC/Driver/std_option.cbs b/clang/test/BSC/Driver/std_option.cbs new file mode 100644 index 0000000000000000000000000000000000000000..d60bdae7ad7defa01022c741e6e39ec889f7ad1e --- /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/BuiltInType/int_conflict_param_type.cbs b/clang/test/BSC/Method/BuiltInType/int_conflict_param_type.cbs new file mode 100644 index 0000000000000000000000000000000000000000..af4bfb2c8ad0877132f55a47368f2656043ec190 --- /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 0000000000000000000000000000000000000000..2007a3dadd2f02b6aae11ec99f016c067730bf95 --- /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_call.cbs b/clang/test/BSC/Method/BuiltInType/int_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..d06846e9da52a0ce83edb60ae9f115f492d4a45e --- /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_function_pointer_undeclared.cbs b/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs new file mode 100644 index 0000000000000000000000000000000000000000..274e6134f1029ea7cbb048eb138ab94118bbb1e0 --- /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 0000000000000000000000000000000000000000..ff822dbe784fd94ea83bdddc3b29351cfed80f03 --- /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_many_arguments.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_many_arguments.cbs new file mode 100644 index 0000000000000000000000000000000000000000..f57769cdb58218aa6e612fe69340efd77e739fd7 --- /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/BuiltInType/int_instance_function_pointer.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs new file mode 100644 index 0000000000000000000000000000000000000000..5869645b7c24023b6ef9bb6b30a0363aeb30ca6a --- /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 0000000000000000000000000000000000000000..6b5890a2b44247855731d80b59d52dd5630bedb5 --- /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 0000000000000000000000000000000000000000..9c747a9ed7713c88ffca994fae4b3132ac7e9c84 --- /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/BuiltInType/int_this_param_check.cbs b/clang/test/BSC/Method/BuiltInType/int_this_param_check.cbs new file mode 100644 index 0000000000000000000000000000000000000000..09fb8971031addb230ce803a6098c1fa5f7ac04a --- /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_conflict_param_type.cbs b/clang/test/BSC/Method/Enum/enum_conflict_param_type.cbs new file mode 100644 index 0000000000000000000000000000000000000000..6155a971d31a3161c93cc1aaa05cb5eabadc130d --- /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 0000000000000000000000000000000000000000..b14149765fc987b533ac71883a457d2cb8f7c3d7 --- /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_call.cbs b/clang/test/BSC/Method/Enum/enum_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..f8cdb1f0366c4c7ae5e0ab5467b834d1fe7193d2 --- /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_function_pointer_undeclared.cbs b/clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs new file mode 100644 index 0000000000000000000000000000000000000000..595e5db3448af620abfc80b4ddabd9d36306239c --- /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 0000000000000000000000000000000000000000..446adccb1d0420bbb8305a7808de088ca1df6211 --- /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_many_arguments.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_many_arguments.cbs new file mode 100644 index 0000000000000000000000000000000000000000..fc497d300863cacca0f454083b77ea92365c985a --- /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/Enum/enum_instance_function_pointer.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs new file mode 100644 index 0000000000000000000000000000000000000000..2681e682d0d6b223695d8169027b8cee02eb9914 --- /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 0000000000000000000000000000000000000000..2042dba0cef01f14ac1dae783ecdb66d74e588d4 --- /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/Enum/enum_this_param_check.cbs b/clang/test/BSC/Method/Enum/enum_this_param_check.cbs new file mode 100644 index 0000000000000000000000000000000000000000..2c68b3fa281306526c2a7fd015c72cf7b71a7835 --- /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_conflict_no_param_1.cbs b/clang/test/BSC/Method/Struct/struct_conflict_no_param_1.cbs new file mode 100644 index 0000000000000000000000000000000000000000..9809668a6c97e3f7e83889a78ff14c006037cd07 --- /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 0000000000000000000000000000000000000000..9e97ea8f68452f281c5a5060de1a7b5773ffdb3e --- /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 0000000000000000000000000000000000000000..0ee0da65372b27d78d4eeeeaa10a8a946eacc85a --- /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 0000000000000000000000000000000000000000..b294fecd1800de0af11eb83348e82b1f1e94f6fa --- /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_call.cbs b/clang/test/BSC/Method/Struct/struct_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..7ae8e560c7585e00f9efdad3edf7ecc1464480a3 --- /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_function_undeclared.cbs b/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs new file mode 100644 index 0000000000000000000000000000000000000000..5849ca25dfcccef4483f59f3ee91ecf2bd30c284 --- /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 0cdd03d421b1fc8bb5c37472477e8031b79486c7..416f7e75c499a23c77a7182c2a9cc0f97ce073f0 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 0000000000000000000000000000000000000000..0e6a528eebfeb75e6346f6fe6385d3e8a0c0788c --- /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 0000000000000000000000000000000000000000..e6c4c2fcd2f365658c675c20a589a017cd20e4aa --- /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_many_arguments.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_many_arguments.cbs new file mode 100644 index 0000000000000000000000000000000000000000..ade797cabd11981dcb909bb92bba2af8709a170f --- /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/Struct/struct_instance_function_multi_declaration.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs new file mode 100644 index 0000000000000000000000000000000000000000..ff1fdddc42e4e7d418d4c975e4a89041a66f34fa --- /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 0000000000000000000000000000000000000000..e7665e9cb10745d8dbe66a79921363b845a6eaff --- /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 0000000000000000000000000000000000000000..ebd1a859d149a3ea21c60898f4ae3d8abcaacdb2 --- /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 0000000000000000000000000000000000000000..d8aa505bd88585a38914d3769d3d6ef5ec866c62 --- /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 ee779a449bcb2a6049519225f1c8aa8419980030..a48f320d52ff73f67dd1878c16a2fa7b3642fd7c 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 0000000000000000000000000000000000000000..995c843391ff8fb32cdb55eb3cfacc7438e52b0d --- /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/Struct/struct_this_param_check.cbs b/clang/test/BSC/Method/Struct/struct_this_param_check.cbs new file mode 100644 index 0000000000000000000000000000000000000000..240cca115de781f6a75af8f761983d9abaece99a --- /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/Struct/struct_toplevel_func.cbs b/clang/test/BSC/Method/Struct/struct_toplevel_func.cbs new file mode 100644 index 0000000000000000000000000000000000000000..268989fa775b8fcc24f5c7388ed731b96f9a9f9f --- /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 0000000000000000000000000000000000000000..1086c2c0007c1dcf3b6e6a1426ccdeab2132efdf --- /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 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 0000000000000000000000000000000000000000..3950cd93c3b15a650ff7426162e14c9f70eaf502 --- /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 0000000000000000000000000000000000000000..bad0123c1d9ea9276ba1354b53bc0e23cb333374 --- /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_call.cbs b/clang/test/BSC/Method/Union/union_function_call.cbs new file mode 100644 index 0000000000000000000000000000000000000000..4ef37fe8dd1e8e7dfbf0568381e1a17024fd3ba2 --- /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_function_pointer_undeclared.cbs b/clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs new file mode 100644 index 0000000000000000000000000000000000000000..8993ac904fb7014f2da6991a3c16c40629e81a7d --- /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_fucntion_many_arguments.cbs b/clang/test/BSC/Method/Union/union_instance_fucntion_many_arguments.cbs new file mode 100644 index 0000000000000000000000000000000000000000..f08e3ceb9fe5eb7175239b982a5c6ba84d389afb --- /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 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 0000000000000000000000000000000000000000..e0bab4d1de389f918a418b553cd811184d103d4b --- /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 0000000000000000000000000000000000000000..3dc1847eb71aaab9fea07ce3e3af72b269b09ac2 --- /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 0000000000000000000000000000000000000000..153b409a1d00078e3f66a947304c31f5586860b8 --- /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/Method/Union/union_this_param_check.cbs b/clang/test/BSC/Method/Union/union_this_param_check.cbs new file mode 100644 index 0000000000000000000000000000000000000000..a1a88c796d022bb0a854e9f6c0435c825560c2db --- /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 diff --git a/clang/test/BSC/pending/StaticMemberFunc.cbs b/clang/test/BSC/Method/ambiguous_1.cbs similarity index 40% rename from clang/test/BSC/pending/StaticMemberFunc.cbs rename to clang/test/BSC/Method/ambiguous_1.cbs index f9b2068cfd7e0f28396081e863e993c65b432786..76aa5ce27c64bd74be347c3029c0c56fb5db68bd 100644 --- a/clang/test/BSC/pending/StaticMemberFunc.cbs +++ b/clang/test/BSC/Method/ambiguous_1.cbs @@ -1,20 +1,18 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // expected-no-diagnostics -typedef struct Foo{ - int a; -}Foo; -int Foo::s1() { +long int::getA1() { return 1; -} +}; -int Foo::s2(struct Foo* other) { - return other->a; -} +unsigned int::getA2() { + return 1; +}; + +short int::getA3() { + return 1; +}; 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/Method/ambiguous_2.cbs b/clang/test/BSC/Method/ambiguous_2.cbs new file mode 100644 index 0000000000000000000000000000000000000000..298ea3a8d0c81aafbe363422374a1b8c1a2bf7d5 --- /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 0000000000000000000000000000000000000000..a87e50fb8c2353f2f67f7fb774e12bf613a781aa --- /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 0000000000000000000000000000000000000000..eba2ecaff588cd61e5d6747c74ec27b37e20d988 --- /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 0677d7e95cdcae9cd84f7dc93703f59958b3417f..02be953ea3ed97d7753273b96e47de93024da5ad 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; }; diff --git a/clang/test/BSC/Method/definition_2.cbs b/clang/test/BSC/Method/definition_2.cbs index c199139b9f729192f946f80f5fa7b1dc58a8071c..93ad7fdba34a2f190e34893bf4f9a1bad6e7faf2 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 3494c223d16c5a76f9f95cc3761ba666d9a1657a..13bd298fce864b16d39fadd7d27a413d880ebe97 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 ea9aeedc9fe5c039db931790879a2c7b584ca8aa..47417394667f691eb4f1464c9132bd2806fc6101 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. -*/ 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 0000000000000000000000000000000000000000..7fe4902bed43b5e9a654d9e528e427aab869faa3 --- /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 0000000000000000000000000000000000000000..bcb0222f9857b066e472b384957b36051c426806 --- /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 0000000000000000000000000000000000000000..a6c7aa7e29f16c7f2a7f7c884960b35eb1f7b04a --- /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 0000000000000000000000000000000000000000..2402e40ffdbe5b6e7123334802554abe399a72d9 --- /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 c8e9187030a7ee4a8195ba39270a172de51fc0f8..0000000000000000000000000000000000000000 --- 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 442a57b87669f0d6e64a3262f570b5d01e2cfe62..0000000000000000000000000000000000000000 --- 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/ThisParamCheck1.cbs b/clang/test/BSC/pending/ThisParamCheck1.cbs deleted file mode 100644 index 05281fbfb1fb9aa16636449232fe2c74d5e35883..0000000000000000000000000000000000000000 --- 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 1fee3762a580a10bde21b4721bce596c6822aa77..0000000000000000000000000000000000000000 --- 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