From e1e2c20b860687131e6c5463df3aa4a6ad41da6a Mon Sep 17 00:00:00 2001 From: zhaoxuhui Date: Mon, 20 Feb 2023 14:34:54 +0800 Subject: [PATCH] [BSC] support function pointer --- clang/include/clang/AST/Decl.h | 2 +- clang/include/clang/AST/DeclCXX.h | 6 +- clang/include/clang/AST/Expr.h | 1 + clang/include/clang/Parse/Parser.h | 4 +- clang/include/clang/Sema/DeclSpec.h | 2 +- clang/include/clang/Sema/Sema.h | 8 +- clang/lib/AST/Decl.cpp | 2 +- clang/lib/Parse/ParseDecl.cpp | 12 +- clang/lib/Parse/ParseExpr.cpp | 40 +- clang/lib/Parse/ParseStmt.cpp | 2 +- clang/lib/Sema/SemaDecl.cpp | 23 +- clang/lib/Sema/SemaExpr.cpp | 19 +- clang/lib/Sema/SemaLookup.cpp | 11 +- clang/lib/Sema/SemaType.cpp | 444 ++++++++++++++++++ .../BuiltInType/int_conflict_param_type.cbs | 6 + .../BuiltInType/int_conflict_return_type.cbs | 6 + .../int_function_pointer_undeclared.cbs | 11 + .../int_instance_function_call.cbs | 11 + .../int_instance_function_pointer.cbs | 15 + .../int_instance_function_with_typedef.cbs | 16 + .../Method/Enum/enum_conflict_param_type.cbs | 11 + .../Method/Enum/enum_conflict_return_type.cbs | 11 + .../Enum/enum_function_pointer_undeclared.cbs | 16 + .../Enum/enum_instance_function_call.cbs | 17 + .../Enum/enum_instance_function_pointer.cbs | 20 + .../enum_instance_function_with_typedef.cbs | 19 + .../Struct/struct_conflict_no_param_1.cbs | 10 + .../Struct/struct_conflict_no_param_2.cbs | 8 + .../Struct/struct_conflict_param_type.cbs | 10 + .../Struct/struct_conflict_return_type.cbs | 10 + .../Struct/struct_function_undeclared.cbs | 15 + .../Struct/struct_instance_function.cbs} | 14 +- .../Struct/struct_instance_function_call.cbs | 16 + .../struct_instance_function_declaration.cbs | 18 + ...ct_instance_function_multi_declaration.cbs | 19 + .../struct_instance_function_not_found.cbs | 16 + .../struct_instance_function_pointer.cbs | 20 + .../struct_instance_function_redefinition.cbs | 19 + ...struct_instance_function_with_typedef.cbs} | 20 +- .../Union/union_conflict_param_type.cbs | 12 + .../Union/union_conflict_return_type.cbs | 12 + .../union_function_pointer_undeclared.cbs | 17 + .../Union/union_instance_function_call.cbs | 18 + .../Union/union_instance_function_pointer.cbs | 21 + .../union_instance_function_with_typedef.cbs | 20 + .../BSC/ParamCheck/this_not_first_param.cbs | 37 ++ .../ParamCheck/this_param_type_no_match.cbs | 40 ++ .../BSC/ParamCheck/this_param_with_const.cbs | 50 ++ .../ParamCheck/this_param_with_volatile.cbs | 49 ++ clang/test/BSC/pending/CallBeforeDefine.cbs | 17 - clang/test/BSC/pending/OverloadFunc.cbs | 24 - clang/test/BSC/pending/StaticMemberFunc.cbs | 20 - clang/test/BSC/pending/ThisParamCheck1.cbs | 17 - clang/test/BSC/pending/ThisParamCheck2.cbs | 21 - 54 files changed, 1151 insertions(+), 154 deletions(-) create mode 100644 clang/test/BSC/Method/BuiltInType/int_conflict_param_type.cbs create mode 100644 clang/test/BSC/Method/BuiltInType/int_conflict_return_type.cbs create mode 100644 clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs create mode 100644 clang/test/BSC/Method/BuiltInType/int_instance_function_call.cbs create mode 100644 clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs create mode 100644 clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_conflict_param_type.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_conflict_return_type.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_instance_function_call.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs create mode 100644 clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_conflict_no_param_1.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_conflict_no_param_2.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_conflict_param_type.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_conflict_return_type.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_function_undeclared.cbs rename clang/test/BSC/{pending/InstanceMemberFunc.cbs => Method/Struct/struct_instance_function.cbs} (39%) create mode 100644 clang/test/BSC/Method/Struct/struct_instance_function_call.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_instance_function_not_found.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs create mode 100644 clang/test/BSC/Method/Struct/struct_instance_function_redefinition.cbs rename clang/test/BSC/{pending/Typedef.cbs => Method/Struct/struct_instance_function_with_typedef.cbs} (45%) create mode 100644 clang/test/BSC/Method/Union/union_conflict_param_type.cbs create mode 100644 clang/test/BSC/Method/Union/union_conflict_return_type.cbs create mode 100644 clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs create mode 100644 clang/test/BSC/Method/Union/union_instance_function_call.cbs create mode 100644 clang/test/BSC/Method/Union/union_instance_function_pointer.cbs create mode 100644 clang/test/BSC/Method/Union/union_instance_function_with_typedef.cbs create mode 100644 clang/test/BSC/ParamCheck/this_not_first_param.cbs create mode 100644 clang/test/BSC/ParamCheck/this_param_type_no_match.cbs create mode 100644 clang/test/BSC/ParamCheck/this_param_with_const.cbs create mode 100644 clang/test/BSC/ParamCheck/this_param_with_volatile.cbs delete mode 100644 clang/test/BSC/pending/CallBeforeDefine.cbs delete mode 100644 clang/test/BSC/pending/OverloadFunc.cbs delete mode 100644 clang/test/BSC/pending/StaticMemberFunc.cbs delete mode 100644 clang/test/BSC/pending/ThisParamCheck1.cbs delete mode 100644 clang/test/BSC/pending/ThisParamCheck2.cbs diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 1e54e91736a3..254e050b7777 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1645,7 +1645,7 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; - bool isThisParam = false; + bool IsThisParam = false; void setObjCMethodScopeInfo(unsigned parameterIndex) { ParmVarDeclBits.IsObjCMethodParam = true; diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 5da1097e8a7a..ca1d3e9c173b 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1955,9 +1955,9 @@ public: static BSCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); bool getHasThisParam() const { - return hasThisParam; + return HasThisParam; } - void setHasThisParam(bool hasThisParam) { this->hasThisParam = hasThisParam; } + void setHasThisParam(bool HasThisParam) { this->HasThisParam = HasThisParam; } QualType getExtendedType() const { return ExtendedType; } void setExtendedType(QualType ExtendedType) { this->ExtendedType = ExtendedType; } @@ -1967,7 +1967,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 a44d06967431..1de83e190e41 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 IsColonColon = false; QualType getType() const { return TR; } void setType(QualType t) { // In C++, the type of an expression is always adjusted so that it diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index ad9bb0a6b91f..7c9c79c5df95 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1789,7 +1789,9 @@ private: bool &NotCastExpr, TypeCastState isTypeCast, bool isVectorLiteral = false, - bool *NotPrimaryExpression = nullptr); + bool *NotPrimaryExpression = nullptr, + QualType T = QualType(), + bool IsColonColon = false); ExprResult ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand = false, TypeCastState isTypeCast = NotTypeCast, diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 11c359717ff8..e4c7fa817d06 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1928,7 +1928,7 @@ public: clear(); } // Used to mark parameters that include 'this'. - bool hasThisParam = false; + bool HasThisParam = false; /// getDeclSpec - Return the declaration-specifier that this declarator was /// declared with. const DeclSpec &getDeclSpec() const { return DS; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d9c176327317..3e87065f4d53 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); + QualType GetTypeForDeclSpec(DeclSpec &BSCScopeSpec); void ConvertBSCScopeSpecToType(Declarator &D, SourceLocation Loc); 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, diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 36c0d620b473..de4b94587b04 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3341,7 +3341,7 @@ void FunctionDecl::setParams(ASTContext &C, unsigned FunctionDecl::getMinRequiredArguments() const { if (getASTContext().getLangOpts().BSC) { int num = getNumParams(); - if (num > 0 && parameters()[0] && parameters()[0]->isThisParam) { + if (num > 0 && parameters()[0] && parameters()[0]->IsThisParam) { num--; } return num; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 20b40259a8c8..dfc9386c9e50 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1978,7 +1978,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, if (!D.getExtendedType().isNull()) { if (auto *MD = dyn_cast(TheDecl)) { MD->setExtendedType(D.getExtendedType()); - MD->setHasThisParam(D.hasThisParam); + MD->setHasThisParam(D.HasThisParam); } } return Actions.ConvertDeclToDeclGroup(TheDecl); @@ -2049,7 +2049,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, D.complete(FirstDecl); if (FirstDecl) { if (auto FD = dyn_cast(FirstDecl)) - FD->setHasThisParam(D.hasThisParam); + FD->setHasThisParam(D.HasThisParam); DeclsInGroup.push_back(FirstDecl); } @@ -6537,9 +6537,9 @@ void Parser::ParseFunctionDeclarator(Declarator &D, if (Tok.isNot(tok::r_paren)) { const Type *typePtr = nullptr; if (!D.getExtendedType().isNull()) { - typePtr = D.getExtendedType().getTypePtr(); + typePtr = D.getExtendedType().getTypePtrOrNull(); if (typePtr) - typePtr = typePtr->getCanonicalTypeUnqualified().getTypePtr(); + typePtr = typePtr->getCanonicalTypeUnqualified().getTypePtrOrNull(); } ParseParameterDeclarationClause(D.getContext(), FirstArgAttrs, ParamInfo, EllipsisLoc, typePtr); @@ -6549,8 +6549,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D, if (ParamInfo.size() > 0) { ParmVarDecl* PD = dyn_cast_or_null(ParamInfo.data()[0].Param); - if (PD && D.getBSCScopeSpec()) - D.hasThisParam = PD->isThisParam; + if (PD && !D.getExtendedType().isNull()) + D.HasThisParam = PD->IsThisParam; } HasProto = ParamInfo.size() || getLangOpts().CPlusPlus || getLangOpts().OpenCL; diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 6acf76d713fd..5831c0ff0917 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -914,7 +914,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, bool &NotCastExpr, TypeCastState isTypeCast, bool isVectorLiteral, - bool *NotPrimaryExpression) { + bool *NotPrimaryExpression, + QualType T, bool IsColonColon) { ExprResult Res; tok::TokenKind SavedKind = Tok.getKind(); auto SavedType = PreferredType; @@ -1036,10 +1037,31 @@ 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 && NextToken().is(tok::identifier) && GetLookAheadToken(2).is(tok::coloncolon)) { + BSCScopeSpec BSS(*this); + ParseBSCScopeSpecifiers(BSS); + QualType T = Actions.GetTypeForDeclSpec(BSS); // get scope type for BSC + IsColonColon = TryConsumeToken(tok::coloncolon); + return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, + isTypeCast, isVectorLiteral, + NotPrimaryExpression, T, IsColonColon); + } + break; case tok::identifier: { // primary-expression: identifier // unqualified-id: identifier // constant: enumeration-constant + if (getLangOpts().BSC && NextToken().is(tok::coloncolon)) { + BSCScopeSpec BSS(*this); + ParseBSCScopeSpecifiers(BSS); + IsColonColon = TryConsumeToken(tok::coloncolon); + return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, + isTypeCast, isVectorLiteral, + NotPrimaryExpression, QualType(), IsColonColon); + break; + } // 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 +1273,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 +1547,16 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t: #include "clang/Basic/OpenCLImageTypes.def" { + if (getLangOpts().BSC &&NextToken().is(tok::coloncolon)) { + BSCScopeSpec BSS(*this); + ParseBSCScopeSpecifiers(BSS); + QualType T = Actions.GetTypeForDeclSpec(BSS); // get scope type for BSC + IsColonColon = TryConsumeToken(tok::coloncolon); + return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, + isTypeCast, isVectorLiteral, + NotPrimaryExpression, T, IsColonColon); + break; + } if (!getLangOpts().CPlusPlus) { Diag(Tok, diag::err_expected_expression); return ExprError(); @@ -1806,6 +1838,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, // These can be followed by postfix-expr pieces. PreferredType = SavedType; + if (Res.get()) + Res.get()->IsColonColon = IsColonColon; Res = ParsePostfixExpressionSuffix(Res); if (getLangOpts().OpenCL) if (Expr *PostfixExpr = Res.get()) { diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 35d3b4b718db..24ad429a31e5 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -211,7 +211,7 @@ Default: if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt || (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) != ParsedStmtContext()) && - (GNUAttributeLoc.isValid() || isDeclarationStatement())) { + (GNUAttributeLoc.isValid() || (isDeclarationStatement() && !(getLangOpts().BSC && (NextToken().is(tok::coloncolon) || GetLookAheadToken(2).is(tok::coloncolon)))))) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy Decl; if (GNUAttributeLoc.isValid()) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 23c28150ae24..a1d0d97b8703 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3675,7 +3675,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(); @@ -13564,7 +13564,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,15 +13609,22 @@ 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(); + } else { + IsThisParam = true; } - isThisParam = true; } else { Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name) << GetNameForDeclarator(D).getName(); @@ -13653,7 +13660,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 27d3901d3d0f..8958b8338948 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2422,7 +2422,8 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand, CorrectionCandidateCallback *CCC, - bool IsInlineAsmIdentifier, Token *KeywordReplacement) { + bool IsInlineAsmIdentifier, Token *KeywordReplacement, + QualType T) { assert(!(IsAddressOfOperand && HasTrailingLParen) && "cannot be direct & operand and have a trailing lparen"); if (SS.isInvalid()) @@ -2472,7 +2473,6 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, if (DependentID) return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, IsAddressOfOperand, TemplateArgs); - // Perform the required lookup. LookupResult R(*this, NameInfo, (Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam) @@ -2497,7 +2497,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, IsAddressOfOperand, TemplateArgs); } else { bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl(); - LookupParsedName(R, S, &SS, !IvarLookupFollowUp); + LookupParsedName(R, S, &SS, !IvarLookupFollowUp, false, T); // If the result might be in a dependent base class, this is a dependent // id-expression. @@ -2522,7 +2522,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // This could be an implicitly declared function reference (legal in C90, // extension in C99, forbidden in C++). - if (R.empty() && HasTrailingLParen && II && !getLangOpts().CPlusPlus) { + if (R.empty() && HasTrailingLParen && II && !getLangOpts().CPlusPlus && !getLangOpts().BSC) { NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S); if (D) R.addDecl(D); } @@ -3423,7 +3423,12 @@ ExprResult Sema::BuildDeclarationNameExpr( valueKind = VK_RValue; break; } - LLVM_FALLTHROUGH; + + // BSC methods are l-values if static, r-values if non-static. + if (cast(VD)->isStatic()) { + valueKind = VK_LValue; + } + break; case Decl::CXXMethod: // If we're referring to a method with an __unknown_anytype @@ -5780,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->IsColonColon) { BSCMethodDecl* MD = dyn_cast_or_null(FDecl); if (MD && MD->getHasThisParam()) { isBSCInstanceFunc = true; @@ -6605,6 +6610,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, ArrayRef Args, SourceLocation RParenLoc, Expr *Config, bool IsExecConfig, ADLCallKind UsesADL) { + bool IsColonColon = Fn->IsColonColon; FunctionDecl *FDecl = dyn_cast_or_null(NDecl); unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0); @@ -6646,6 +6652,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (Result.isInvalid()) return ExprError(); Fn = Result.get(); + Fn->IsColonColon = IsColonColon; // Check for a valid function type, but only if it is not a builtin which // requires custom type checking. These will be handled by diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 2a5206ca6a97..db331d6df6d0 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -2406,7 +2406,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 +2437,14 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, return false; } + if (!T.isNull() && getLangOpts().BSC) { + DeclContext *DC = getASTContext().BSCDeclContextMap[T.getCanonicalType().getTypePtr()]; + if (DC) + return LookupQualifiedName(R, DC); + else + Diag(R.getNameLoc(), diag::err_undeclared_var_use) << R.getLookupName(); + } + // Perform unqualified name lookup starting in the given scope. return LookupName(R, S, AllowBuiltinCreation); } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index c5dd268dd134..b63ecbde359e 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1276,6 +1276,450 @@ static QualType ConvertConstrainedAutoDeclSpecToType(Sema &S, DeclSpec &DS, TemplateArgs); } +QualType Sema::GetTypeForDeclSpec(DeclSpec &BSCScopeSpec) { + DeclSpec &DS = BSCScopeSpec; + + QualType Result; + switch (DS.getTypeSpecType()) { + case DeclSpec::TST_void: + Result = Context.VoidTy; + break; + case DeclSpec::TST_char: + if (DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified) + Result = Context.CharTy; + else if (DS.getTypeSpecSign() == TypeSpecifierSign::Signed) + Result = Context.SignedCharTy; + else { + assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned && + "Unknown TSS value"); + Result = Context.UnsignedCharTy; + } + break; + case DeclSpec::TST_wchar: + if (DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified) + Result = Context.WCharTy; + else if (DS.getTypeSpecSign() == TypeSpecifierSign::Signed) { + Diag(DS.getTypeSpecSignLoc(), diag::ext_wchar_t_sign_spec) + << DS.getSpecifierName(DS.getTypeSpecType(), + Context.getPrintingPolicy()); + Result = Context.getSignedWCharType(); + } else { + assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned && + "Unknown TSS value"); + Diag(DS.getTypeSpecSignLoc(), diag::ext_wchar_t_sign_spec) + << DS.getSpecifierName(DS.getTypeSpecType(), + Context.getPrintingPolicy()); + Result = Context.getUnsignedWCharType(); + } + break; + case DeclSpec::TST_char8: + assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && + "Unknown TSS value"); + Result = Context.Char8Ty; + break; + case DeclSpec::TST_char16: + assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && + "Unknown TSS value"); + Result = Context.Char16Ty; + break; + case DeclSpec::TST_char32: + assert(DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && + "Unknown TSS value"); + Result = Context.Char32Ty; + break; + case DeclSpec::TST_int: { + if (DS.getTypeSpecSign() != TypeSpecifierSign::Unsigned) { + switch (DS.getTypeSpecWidth()) { + case TypeSpecifierWidth::Unspecified: + Result = Context.IntTy; + break; + case TypeSpecifierWidth::Short: + Result = Context.ShortTy; + break; + case TypeSpecifierWidth::Long: + Result = Context.LongTy; + break; + case TypeSpecifierWidth::LongLong: + Result = Context.LongLongTy; + + // 'long long' is a C99 or C++11 feature. + if (!getLangOpts().C99) { + if (getLangOpts().CPlusPlus) + Diag(DS.getTypeSpecWidthLoc(), + getLangOpts().CPlusPlus11 ? + diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong); + else + Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong); + } + break; + } + } else { + switch (DS.getTypeSpecWidth()) { + case TypeSpecifierWidth::Unspecified: + Result = Context.UnsignedIntTy; + break; + case TypeSpecifierWidth::Short: + Result = Context.UnsignedShortTy; + break; + case TypeSpecifierWidth::Long: + Result = Context.UnsignedLongTy; + break; + case TypeSpecifierWidth::LongLong: + Result = Context.UnsignedLongLongTy; + + // 'long long' is a C99 or C++11 feature. + if (!getLangOpts().C99) { + if (getLangOpts().CPlusPlus) + Diag(DS.getTypeSpecWidthLoc(), + getLangOpts().CPlusPlus11 ? + diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong); + else + Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong); + } + break; + } + } + break; + } + case DeclSpec::TST_extint: { + if (!Context.getTargetInfo().hasExtIntType()) + Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) + << "_ExtInt"; + Result = + BuildExtIntType(DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned, + DS.getRepAsExpr(), DS.getBeginLoc()); + if (Result.isNull()) { + Result = Context.IntTy; + } + break; + } + case DeclSpec::TST_accum: { + switch (DS.getTypeSpecWidth()) { + case TypeSpecifierWidth::Short: + Result = Context.ShortAccumTy; + break; + case TypeSpecifierWidth::Unspecified: + Result = Context.AccumTy; + break; + case TypeSpecifierWidth::Long: + Result = Context.LongAccumTy; + break; + case TypeSpecifierWidth::LongLong: + llvm_unreachable("Unable to specify long long as _Accum width"); + } + + if (DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned) + Result = Context.getCorrespondingUnsignedType(Result); + + if (DS.isTypeSpecSat()) + Result = Context.getCorrespondingSaturatedType(Result); + + break; + } + case DeclSpec::TST_fract: { + switch (DS.getTypeSpecWidth()) { + case TypeSpecifierWidth::Short: + Result = Context.ShortFractTy; + break; + case TypeSpecifierWidth::Unspecified: + Result = Context.FractTy; + break; + case TypeSpecifierWidth::Long: + Result = Context.LongFractTy; + break; + case TypeSpecifierWidth::LongLong: + llvm_unreachable("Unable to specify long long as _Fract width"); + } + + if (DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned) + Result = Context.getCorrespondingUnsignedType(Result); + + if (DS.isTypeSpecSat()) + Result = Context.getCorrespondingSaturatedType(Result); + + break; + } + case DeclSpec::TST_int128: + if (!Context.getTargetInfo().hasInt128Type() && + !getLangOpts().SYCLIsDevice && + !(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice)) + Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) + << "__int128"; + if (DS.getTypeSpecSign() == TypeSpecifierSign::Unsigned) + Result = Context.UnsignedInt128Ty; + else + Result = Context.Int128Ty; + break; + case DeclSpec::TST_float16: + // CUDA host and device may have different _Float16 support, therefore + // do not diagnose _Float16 usage to avoid false alarm. + // ToDo: more precise diagnostics for CUDA. + if (!Context.getTargetInfo().hasFloat16Type() && !getLangOpts().CUDA && + !(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice)) + Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) + << "_Float16"; + Result = Context.Float16Ty; + break; + case DeclSpec::TST_half: Result = Context.HalfTy; break; + case DeclSpec::TST_BFloat16: + if (!Context.getTargetInfo().hasBFloat16Type()) + Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) + << "__bf16"; + Result = Context.BFloat16Ty; + break; + case DeclSpec::TST_float: Result = Context.FloatTy; break; + case DeclSpec::TST_double: + if (DS.getTypeSpecWidth() == TypeSpecifierWidth::Long) + Result = Context.LongDoubleTy; + else + Result = Context.DoubleTy; + break; + case DeclSpec::TST_float128: + if (!Context.getTargetInfo().hasFloat128Type() && + !getLangOpts().SYCLIsDevice && + !(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice)) + Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) + << "__float128"; + Result = Context.Float128Ty; + break; + case DeclSpec::TST_bool: + Result = Context.BoolTy; // _Bool or bool + break; + case DeclSpec::TST_decimal32: // _Decimal32 + case DeclSpec::TST_decimal64: // _Decimal64 + case DeclSpec::TST_decimal128: // _Decimal128 + Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported); + Result = Context.IntTy; + break; + case DeclSpec::TST_class: + case DeclSpec::TST_enum: + case DeclSpec::TST_union: + case DeclSpec::TST_struct: + case DeclSpec::TST_interface: { + TagDecl *D = dyn_cast_or_null(DS.getRepAsDecl()); + if (!D) { + // This can happen in C++ with ambiguous lookups. + Result = Context.IntTy; + break; + } + + // If the type is deprecated or unavailable, diagnose it. + DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc()); + + assert(DS.getTypeSpecWidth() == TypeSpecifierWidth::Unspecified && + DS.getTypeSpecComplex() == 0 && + DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && + "No qualifiers on tag names!"); + + // TypeQuals handled by caller. + Result = Context.getTypeDeclType(D); + + // In both C and C++, make an ElaboratedType. + ElaboratedTypeKeyword Keyword + = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType()); + Result = getElaboratedType(Keyword, DS.getTypeSpecScope(), Result, + DS.isTypeSpecOwned() ? D : nullptr); + break; + } + case DeclSpec::TST_typename: { + assert(DS.getTypeSpecWidth() == TypeSpecifierWidth::Unspecified && + DS.getTypeSpecComplex() == 0 && + DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && + "Can't handle qualifiers on typedef names yet!"); + Result = GetTypeFromParser(DS.getRepAsType()); + + // TypeQuals handled by caller. + break; + } + case DeclSpec::TST_typeofType: + // FIXME: Preserve type source info. + Result = GetTypeFromParser(DS.getRepAsType()); + assert(!Result.isNull() && "Didn't get a type for typeof?"); + if (!Result->isDependentType()) + if (const TagType *TT = Result->getAs()) + DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc()); + // TypeQuals handled by caller. + Result = Context.getTypeOfType(Result); + break; + case DeclSpec::TST_typeofExpr: { + Expr *E = DS.getRepAsExpr(); + assert(E && "Didn't get an expression for typeof?"); + // TypeQuals handled by caller. + Result = BuildTypeofExprType(E, DS.getTypeSpecTypeLoc()); + if (Result.isNull()) { + Result = Context.IntTy; + } + break; + } + case DeclSpec::TST_decltype: { + Expr *E = DS.getRepAsExpr(); + assert(E && "Didn't get an expression for decltype?"); + // TypeQuals handled by caller. + Result = BuildDecltypeType(E, DS.getTypeSpecTypeLoc()); + if (Result.isNull()) { + Result = Context.IntTy; + } + break; + } + case DeclSpec::TST_underlyingType: + Result = GetTypeFromParser(DS.getRepAsType()); + assert(!Result.isNull() && "Didn't get a type for __underlying_type?"); + Result = BuildUnaryTransformType(Result, + UnaryTransformType::EnumUnderlyingType, + DS.getTypeSpecTypeLoc()); + if (Result.isNull()) { + Result = Context.IntTy; + } + break; + + case DeclSpec::TST_auto: + if (DS.isConstrainedAuto()) { + Result = ConvertConstrainedAutoDeclSpecToType(*this, DS, + AutoTypeKeyword::Auto); + break; + } + Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false); + break; + + case DeclSpec::TST_auto_type: + Result = Context.getAutoType(QualType(), AutoTypeKeyword::GNUAutoType, false); + break; + + case DeclSpec::TST_decltype_auto: + if (DS.isConstrainedAuto()) { + Result = + ConvertConstrainedAutoDeclSpecToType(*this, DS, + AutoTypeKeyword::DecltypeAuto); + break; + } + Result = Context.getAutoType(QualType(), AutoTypeKeyword::DecltypeAuto, + /*IsDependent*/ false); + break; + + case DeclSpec::TST_unknown_anytype: + Result = Context.UnknownAnyTy; + break; + + case DeclSpec::TST_atomic: + Result = GetTypeFromParser(DS.getRepAsType()); + assert(!Result.isNull() && "Didn't get a type for _Atomic?"); + Result = BuildAtomicType(Result, DS.getTypeSpecTypeLoc()); + if (Result.isNull()) { + Result = Context.IntTy; + } + break; + +#define GENERIC_IMAGE_TYPE(ImgType, Id) \ + case DeclSpec::TST_##ImgType##_t: \ + switch (getImageAccess(DS.getAttributes())) { \ + case OpenCLAccessAttr::Keyword_write_only: \ + Result = Context.Id##WOTy; \ + break; \ + case OpenCLAccessAttr::Keyword_read_write: \ + Result = Context.Id##RWTy; \ + break; \ + case OpenCLAccessAttr::Keyword_read_only: \ + Result = Context.Id##ROTy; \ + break; \ + case OpenCLAccessAttr::SpellingNotCalculated: \ + llvm_unreachable("Spelling not yet calculated"); \ + } \ + break; +#include "clang/Basic/OpenCLImageTypes.def" + + case DeclSpec::TST_error: + Result = Context.IntTy; + break; + } + + bool IsFixedPointType = DS.getTypeSpecType() == DeclSpec::TST_accum || + DS.getTypeSpecType() == DeclSpec::TST_fract; + + // Only fixed point types can be saturated + if (DS.isTypeSpecSat() && !IsFixedPointType) + Diag(DS.getTypeSpecSatLoc(), diag::err_invalid_saturation_spec) + << DS.getSpecifierName(DS.getTypeSpecType(), + Context.getPrintingPolicy()); + + // Handle complex types. + if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) { + if (getLangOpts().Freestanding) + Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex); + Result = Context.getComplexType(Result); + } else if (DS.isTypeAltiVecVector()) { + unsigned typeSize = static_cast(Context.getTypeSize(Result)); + assert(typeSize > 0 && "type size for vector must be greater than 0 bits"); + VectorType::VectorKind VecKind = VectorType::AltiVecVector; + if (DS.isTypeAltiVecPixel()) + VecKind = VectorType::AltiVecPixel; + else if (DS.isTypeAltiVecBool()) + VecKind = VectorType::AltiVecBool; + Result = Context.getVectorType(Result, 128/typeSize, VecKind); + } + + // FIXME: Imaginary. + if (DS.getTypeSpecComplex() == DeclSpec::TSC_imaginary) + Diag(DS.getTypeSpecComplexLoc(), diag::err_imaginary_not_supported); + + // Apply const/volatile/restrict qualifiers to T. + if (unsigned TypeQuals = DS.getTypeQualifiers()) { + // Warn about CV qualifiers on function types. + // C99 6.7.3p8: + // If the specification of a function type includes any type qualifiers, + // the behavior is undefined. + // C++11 [dcl.fct]p7: + // The effect of a cv-qualifier-seq in a function declarator is not the + // same as adding cv-qualification on top of the function type. In the + // latter case, the cv-qualifiers are ignored. + if (Result->isFunctionType()) { + diagnoseAndRemoveTypeQualifiers( + *this, DS, TypeQuals, Result, DeclSpec::TQ_const | DeclSpec::TQ_volatile, + getLangOpts().CPlusPlus + ? diag::warn_typecheck_function_qualifiers_ignored + : diag::warn_typecheck_function_qualifiers_unspecified); + // No diagnostic for 'restrict' or '_Atomic' applied to a + // function type; we'll diagnose those later, in BuildQualifiedType. + } + + // C++11 [dcl.ref]p1: + // Cv-qualified references are ill-formed except when the + // cv-qualifiers are introduced through the use of a typedef-name + // or decltype-specifier, in which case the cv-qualifiers are ignored. + // + // There don't appear to be any other contexts in which a cv-qualified + // reference type could be formed, so the 'ill-formed' clause here appears + // to never happen. + if (TypeQuals && Result->isReferenceType()) { + diagnoseAndRemoveTypeQualifiers( + *this, DS, TypeQuals, Result, + DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_atomic, + diag::warn_typecheck_reference_qualifiers); + } + + // C90 6.5.3 constraints: "The same type qualifier shall not appear more + // than once in the same specifier-list or qualifier-list, either directly + // or via one or more typedefs." + if (!getLangOpts().C99 && !getLangOpts().CPlusPlus + && TypeQuals & Result.getCVRQualifiers()) { + if (TypeQuals & DeclSpec::TQ_const && Result.isConstQualified()) { + Diag(DS.getConstSpecLoc(), diag::ext_duplicate_declspec) + << "const"; + } + + if (TypeQuals & DeclSpec::TQ_volatile && Result.isVolatileQualified()) { + Diag(DS.getVolatileSpecLoc(), diag::ext_duplicate_declspec) + << "volatile"; + } + + // C90 doesn't have restrict nor _Atomic, so it doesn't force us to + // produce a warning in this case. + } + } + + assert(!Result.isNull() && "This function should not return a null type"); + return Result; +} + /// Convert the specified declspec to the appropriate type /// object. /// \param state Specifies the declarator containing the declaration specifier diff --git a/clang/test/BSC/Method/BuiltInType/int_conflict_param_type.cbs b/clang/test/BSC/Method/BuiltInType/int_conflict_param_type.cbs new file mode 100644 index 000000000000..af4bfb2c8ad0 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_conflict_param_type.cbs @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -verify %s + +void int::increase(int a); // expected-note {{previous declaration is here}} +void int::increase(int* this) { // expected-error {{conflicting types for 'increase'}} + *this = *this +1; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_conflict_return_type.cbs b/clang/test/BSC/Method/BuiltInType/int_conflict_return_type.cbs new file mode 100644 index 000000000000..2007a3dadd2f --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_conflict_return_type.cbs @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -verify %s + +double int::increase(int* this); // expected-note {{previous declaration is here}} +void int::increase(int* this) { // expected-error {{conflicting types for 'increase'}} + *this = *this +1; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs b/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs new file mode 100644 index 000000000000..274e6134f102 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_function_pointer_undeclared.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +int getA() { + return 1; +} + +int main() { + int (*fp)() = int::getA; // expected-error {{use of undeclared identifier 'getA'}} + int (*fp1)() = &int::getA; // expected-error {{use of undeclared identifier 'getA'}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_call.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_call.cbs new file mode 100644 index 000000000000..ff822dbe784f --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_call.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +void int::increase(int* this) { // expected-note {{'increase' declared here}} + *this = *this + 1; +} + +int main() { + int x = 1; + x.increase(&x); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs new file mode 100644 index 000000000000..5869645b7c24 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_pointer.cbs @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +void int::increase(int* this) { + *this = *this +1; +} + +int main() { + int foo = 1; + void (*fp1)(int *) = int::increase; + void (*fp2)(int *) = &int::increase; + fp1(&foo); + fp2(&foo); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs b/clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs new file mode 100644 index 000000000000..6b5890a2b442 --- /dev/null +++ b/clang/test/BSC/Method/BuiltInType/int_instance_function_with_typedef.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +typedef int bscInt; + +void bscInt::increase_1(bscInt* this) { + *this = *this + 1; +} + +void int::increase_2(bscInt* this) { + *this = *this + 1; +} + +void int::increase_3(int* this) { + *this = *this + 1; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_conflict_param_type.cbs b/clang/test/BSC/Method/Enum/enum_conflict_param_type.cbs new file mode 100644 index 000000000000..6155a971d31a --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_conflict_param_type.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int enum E::getA(int a); // expected-note {{previous declaration is here}} +int enum E::getA(enum E* this) { // expected-error {{conflicting types for 'getA'}} + return X4; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_conflict_return_type.cbs b/clang/test/BSC/Method/Enum/enum_conflict_return_type.cbs new file mode 100644 index 000000000000..b14149765fc9 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_conflict_return_type.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +double enum E::getA(enum E* this); // expected-note {{previous declaration is here}} +int enum E::getA(enum E* this) { // expected-error {{conflicting types for 'getA'}} + return X4; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs b/clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs new file mode 100644 index 000000000000..595e5db3448a --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_function_pointer_undeclared.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int getA() { + return 1; +} + +int main() { + int (*fp)() = enum E::getA; // expected-error {{use of undeclared identifier 'getA'}} + int (*fp1)() = &enum E::getA; // expected-error {{use of undeclared identifier 'getA'}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_call.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_call.cbs new file mode 100644 index 000000000000..446adccb1d04 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_instance_function_call.cbs @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -verify %s + +enum E { + X3, + X4 +}; + +int enum E::getA(enum E* this) { // expected-note {{'getA' declared here}} + return X4; +} + + +int main() { + enum E e= X3; + e.getA(&e); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs new file mode 100644 index 000000000000..2681e682d0d6 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_instance_function_pointer.cbs @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +enum E { + X3, + X4 +}; + +int enum E::getA(enum E* this) { + return X4; +} + +int main() { + enum E foo = X3; + int (*fp1)(enum E *) = enum E::getA; + int (*fp2)(enum E *) = &enum E::getA; + fp1(&foo); + fp2(&foo); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs b/clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs new file mode 100644 index 000000000000..2042dba0cef0 --- /dev/null +++ b/clang/test/BSC/Method/Enum/enum_instance_function_with_typedef.cbs @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +typedef enum E { + X3, + X4 +}E; + +int E::getX4_1(E* this) { + return X4; +} + +int E::getX4_2(enum E* this) { + return X4; +} + +int enum E::getX4_3(enum E* this) { + return X4; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_conflict_no_param_1.cbs b/clang/test/BSC/Method/Struct/struct_conflict_no_param_1.cbs new file mode 100644 index 000000000000..9809668a6c97 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_conflict_no_param_1.cbs @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(); // expected-note {{previous declaration is here}} +int struct Foo::getA(struct Foo* this) { // expected-error {{conflicting types for 'getA'}} + return this->a; +} diff --git a/clang/test/BSC/Method/Struct/struct_conflict_no_param_2.cbs b/clang/test/BSC/Method/Struct/struct_conflict_no_param_2.cbs new file mode 100644 index 000000000000..9e97ea8f6845 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_conflict_no_param_2.cbs @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(); // expected-note {{previous declaration is here}} +int struct Foo::getA(struct Foo* this); // expected-error {{conflicting types for 'getA'}} diff --git a/clang/test/BSC/Method/Struct/struct_conflict_param_type.cbs b/clang/test/BSC/Method/Struct/struct_conflict_param_type.cbs new file mode 100644 index 000000000000..0ee0da65372b --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_conflict_param_type.cbs @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(int a); // expected-note {{previous declaration is here}} +int struct Foo::getA(struct Foo* this) { // expected-error {{conflicting types for 'getA'}} + return this->a; +} diff --git a/clang/test/BSC/Method/Struct/struct_conflict_return_type.cbs b/clang/test/BSC/Method/Struct/struct_conflict_return_type.cbs new file mode 100644 index 000000000000..b294fecd1800 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_conflict_return_type.cbs @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +double struct Foo::getA(struct Foo* this); // expected-note {{previous declaration is here}} +int struct Foo::getA(struct Foo* this) { // expected-error {{conflicting types for 'getA'}} + return this->a; +} diff --git a/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs b/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs new file mode 100644 index 000000000000..5849ca25dfcc --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_function_undeclared.cbs @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int getA() { + return 1; +} + +int main() { + int (*fp)() = struct Foo::getA; // expected-error {{use of undeclared identifier 'getA'}} + int (*fp1)() = &struct Foo::getA; // expected-error {{use of undeclared identifier 'getA'}} + return 0; +} diff --git a/clang/test/BSC/pending/InstanceMemberFunc.cbs b/clang/test/BSC/Method/Struct/struct_instance_function.cbs similarity index 39% rename from clang/test/BSC/pending/InstanceMemberFunc.cbs rename to clang/test/BSC/Method/Struct/struct_instance_function.cbs index 0cdd03d421b1..416f7e75c499 100644 --- a/clang/test/BSC/pending/InstanceMemberFunc.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_function.cbs @@ -1,17 +1,17 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -verify %s // expected-no-diagnostics -typedef struct Foo{ + +struct Foo { int a; -}Foo; +}; -int Foo::getA(struct Foo* this) { +int struct Foo::getA(struct Foo* this) { return this->a; } + int main() { - Foo foo; - foo.a = 42; + struct Foo foo = {.a = 1}; foo.getA(); - Foo::getA(&foo); return 0; } \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_call.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_call.cbs new file mode 100644 index 000000000000..0e6a528eebfe --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_call.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this) { // expected-note {{'getA' declared here}} + return this->a; +} + + +int main() { + struct Foo foo = {.a = 1}; + foo.getA(&foo); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs new file mode 100644 index 000000000000..e6c4c2fcd2f3 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_declaration.cbs @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this); + +int main() { + struct Foo foo = {.a = 1}; + foo.getA(); + return 0; +} + +int struct Foo::getA(struct Foo* this) { + return this->a; +} diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs new file mode 100644 index 000000000000..ff1fdddc42e4 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_multi_declaration.cbs @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this); +int struct Foo::getA(struct Foo* this); + +int main() { + struct Foo foo = {.a = 1}; + foo.getA(); + return 0; +} + +int struct Foo::getA(struct Foo* this) { + return this->a; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_not_found.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_not_found.cbs new file mode 100644 index 000000000000..e7665e9cb107 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_not_found.cbs @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this) { + return this->a; +} + + +int main() { + struct Foo foo = {.a = 1}; + foo.getB(); // expected-error {{no member named 'getB' in 'struct Foo'}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs new file mode 100644 index 000000000000..ebd1a859d149 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_pointer.cbs @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this) { + return this->a; +} + + +int main() { + struct Foo foo = {.a = 1}; + int (*fp1)(struct Foo *) = struct Foo::getA; + int (*fp2)(struct Foo *) = &struct Foo::getA; + fp1(&foo); + fp2(&foo); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Struct/struct_instance_function_redefinition.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_redefinition.cbs new file mode 100644 index 000000000000..d8aa505bd885 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_instance_function_redefinition.cbs @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int struct Foo::getA(struct Foo* this) { // expected-note {{previous definition is here}} + return this->a; +} + +int struct Foo::getA(struct Foo* this) { // expected-error {{redefinition of 'getA'}} + return this->a; +} + +int main() { + struct Foo foo = {.a = 1}; + foo.getA(); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/pending/Typedef.cbs b/clang/test/BSC/Method/Struct/struct_instance_function_with_typedef.cbs similarity index 45% rename from clang/test/BSC/pending/Typedef.cbs rename to clang/test/BSC/Method/Struct/struct_instance_function_with_typedef.cbs index ee779a449bcb..a48f320d52ff 100644 --- a/clang/test/BSC/pending/Typedef.cbs +++ b/clang/test/BSC/Method/Struct/struct_instance_function_with_typedef.cbs @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -verify %s // expected-no-diagnostics -struct Foo { + +typedef struct Foo { int a; int b; -}; -typedef struct Foo Foo; +}Foo; int Foo::getB(Foo* this) { return this->b; @@ -14,12 +14,6 @@ int Foo::getAPlusB(struct Foo* this) { return this->a + this->b; } -int main() { - Foo foo; - foo.a = 42; - foo.b = 2023; - int b = foo.getB(); - int ab = foo.getAPlusB(); - return 0; -} - +int struct Foo::getA(struct Foo* this) { + return this->a; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_conflict_param_type.cbs b/clang/test/BSC/Method/Union/union_conflict_param_type.cbs new file mode 100644 index 000000000000..3950cd93c3b1 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_conflict_param_type.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(int a); // expected-note {{previous declaration is here}} +int union SimpleUnion::getA(union SimpleUnion * this) { // expected-error {{conflicting types for 'getA'}} + return this->ui; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_conflict_return_type.cbs b/clang/test/BSC/Method/Union/union_conflict_return_type.cbs new file mode 100644 index 000000000000..bad0123c1d9e --- /dev/null +++ b/clang/test/BSC/Method/Union/union_conflict_return_type.cbs @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +double union SimpleUnion::getA(union SimpleUnion * this); // expected-note {{previous declaration is here}} +int union SimpleUnion::getA(union SimpleUnion * this) { // expected-error {{conflicting types for 'getA'}} + return this->ui; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs b/clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs new file mode 100644 index 000000000000..8993ac904fb7 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_function_pointer_undeclared.cbs @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int getA() { + return 1; +} + +int main() { + int (*fp)() = union SimpleUnion::getA; // expected-error {{use of undeclared identifier 'getA'}} + int (*fp1)() = &union SimpleUnion::getA; // expected-error {{use of undeclared identifier 'getA'}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_instance_function_call.cbs b/clang/test/BSC/Method/Union/union_instance_function_call.cbs new file mode 100644 index 000000000000..e0bab4d1de38 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_instance_function_call.cbs @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -verify %s + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(union SimpleUnion* this) { // expected-note {{'getA' declared here}} + return this->ui; +} + + +int main() { + union SimpleUnion u = {.ui = 1}; + u.getA(&u); // expected-error {{too many arguments to function call, expected 0, have 1}} + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_instance_function_pointer.cbs b/clang/test/BSC/Method/Union/union_instance_function_pointer.cbs new file mode 100644 index 000000000000..3dc1847eb71a --- /dev/null +++ b/clang/test/BSC/Method/Union/union_instance_function_pointer.cbs @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(union SimpleUnion * this) { + return this->ui; +} + +int main() { + union SimpleUnion foo = {.ui = 1}; + int (*fp1)(union SimpleUnion *) = union SimpleUnion::getA; + int (*fp2)(union SimpleUnion *) = &union SimpleUnion::getA; + fp1(&foo); + fp2(&foo); + return 0; +} \ No newline at end of file diff --git a/clang/test/BSC/Method/Union/union_instance_function_with_typedef.cbs b/clang/test/BSC/Method/Union/union_instance_function_with_typedef.cbs new file mode 100644 index 000000000000..153b409a1d00 --- /dev/null +++ b/clang/test/BSC/Method/Union/union_instance_function_with_typedef.cbs @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +typedef union SimpleUnion { + float uf; + int ui; + char uc; +}SimpleUnion; + +int SimpleUnion::getui_1(SimpleUnion* this) { + return this->ui; +} + +int SimpleUnion::getui_2(union SimpleUnion* this) { + return this->ui; +} + +int union SimpleUnion::getui_3(union SimpleUnion* this) { + return this->ui; +} \ No newline at end of file diff --git a/clang/test/BSC/ParamCheck/this_not_first_param.cbs b/clang/test/BSC/ParamCheck/this_not_first_param.cbs new file mode 100644 index 000000000000..7fe4902bed43 --- /dev/null +++ b/clang/test/BSC/ParamCheck/this_not_first_param.cbs @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -verify %s + +// struct +struct Foo { + int a; +}; + +int struct Foo::getA(int b, struct Foo* this) { // expected-error {{'this' cannot be the name of a parameter}} + return this->a; +} + +// enum +enum E { + X3, + X4 +}; + +int enum E::getA(int b, enum E* this) { // expected-error {{'this' cannot be the name of a parameter}} + return X4; +} + +// union +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(int b, union SimpleUnion* this) { // expected-error {{'this' cannot be the name of a parameter}} + return this->ui; +} + +// BuiltinType +void int::increase(int b, int* this) { // expected-error {{'this' cannot be the name of a parameter}} + *this = *this + b; +} + diff --git a/clang/test/BSC/ParamCheck/this_param_type_no_match.cbs b/clang/test/BSC/ParamCheck/this_param_type_no_match.cbs new file mode 100644 index 000000000000..bcb0222f9857 --- /dev/null +++ b/clang/test/BSC/ParamCheck/this_param_type_no_match.cbs @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -verify %s + +// struct +struct Foo { + int a; +}; + +struct Bar { + int a; +}; + +int struct Foo::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} + return this->a; +} + +// enum +enum E { + X3, + X4 +}; + +int enum E::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} + return this->a; +} + +// union +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} + return this->a; +} + +// BuiltinType +int int::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} + return this->a; +} \ No newline at end of file diff --git a/clang/test/BSC/ParamCheck/this_param_with_const.cbs b/clang/test/BSC/ParamCheck/this_param_with_const.cbs new file mode 100644 index 000000000000..a6c7aa7e29f1 --- /dev/null +++ b/clang/test/BSC/ParamCheck/this_param_with_const.cbs @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +// struct +struct Foo { + int a; +}; + +int struct Foo::getA(const struct Foo* this) { + return this->a; +} + +// enum +enum E { + X3, + X4 +}; + +int enum E::getA(const enum E* this) { + return X4; +} + +// union +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(const union SimpleUnion* this) { + return this->ui; +} + +// BuiltinType +int int::getA(const int* this) { + return *this; +} + +int main() { + struct Foo foo ={.a = 42}; + foo.getA(); + enum E e= X3; + e.getA(); + union SimpleUnion u = {.ui = 1}; + u.getA(); + int one = 1; + one.getA(); + return 0; +} + diff --git a/clang/test/BSC/ParamCheck/this_param_with_volatile.cbs b/clang/test/BSC/ParamCheck/this_param_with_volatile.cbs new file mode 100644 index 000000000000..2402e40ffdbe --- /dev/null +++ b/clang/test/BSC/ParamCheck/this_param_with_volatile.cbs @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +// struct +struct Foo { + int a; +}; + +int struct Foo::getA(volatile struct Foo* this) { + return this->a; +} + +// enum +enum E { + X3, + X4 +}; + +int enum E::getA(volatile enum E* this) { + return X4; +} + +// union +union SimpleUnion { + float uf; + int ui; + char uc; +}; + +int union SimpleUnion::getA(volatile union SimpleUnion* this) { + return this->ui; +} + +// BuiltinType +int int::getA(volatile int* this) { + return *this; +} + +int main() { + struct Foo foo ={.a = 42}; + foo.getA(); + enum E e= X3; + e.getA(); + union SimpleUnion u = {.ui = 1}; + u.getA(); + int one = 1; + one.getA(); + return 0; +} diff --git a/clang/test/BSC/pending/CallBeforeDefine.cbs b/clang/test/BSC/pending/CallBeforeDefine.cbs deleted file mode 100644 index c8e9187030a7..000000000000 --- a/clang/test/BSC/pending/CallBeforeDefine.cbs +++ /dev/null @@ -1,17 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics -typedef struct Foo { - int a; -}Foo; - -int Foo::getA(struct Foo* this); - -int main() { - struct Foo foo; - foo.a = 42; - return foo.getA(); -} - -int Foo::getA(struct Foo* this) { - return this->a; -} \ No newline at end of file diff --git a/clang/test/BSC/pending/OverloadFunc.cbs b/clang/test/BSC/pending/OverloadFunc.cbs deleted file mode 100644 index 442a57b87669..000000000000 --- a/clang/test/BSC/pending/OverloadFunc.cbs +++ /dev/null @@ -1,24 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -struct Foo { - int a; -}; -typedef struct Foo F; - -int F::f2(F* this) { -// expected-note@-1 {{previous definition is here}} -// expected-note@-2 {{passing argument to parameter 'this' here}} - return 1; -} - -int F::f2(F* this, int a) { // expected-error {{conflicting types for 'f2'}} - return a; -} - -int main(){ - Foo foo; - foo.a = 1; - foo.f2(); - foo.f2(1); // expected-warning {{incompatible integer to pointer conversion passing 'int' to parameter of type 'F *' (aka 'struct Foo *')}} - return 0; -} \ No newline at end of file diff --git a/clang/test/BSC/pending/StaticMemberFunc.cbs b/clang/test/BSC/pending/StaticMemberFunc.cbs deleted file mode 100644 index f9b2068cfd7e..000000000000 --- a/clang/test/BSC/pending/StaticMemberFunc.cbs +++ /dev/null @@ -1,20 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics -typedef struct Foo{ - int a; -}Foo; - -int Foo::s1() { - return 1; -} - -int Foo::s2(struct Foo* other) { - return other->a; -} - -int main() { - struct Foo x = {0}; - Foo::s1(); - Foo::s2(&x); - return 0; -} \ No newline at end of file diff --git a/clang/test/BSC/pending/ThisParamCheck1.cbs b/clang/test/BSC/pending/ThisParamCheck1.cbs deleted file mode 100644 index 05281fbfb1fb..000000000000 --- a/clang/test/BSC/pending/ThisParamCheck1.cbs +++ /dev/null @@ -1,17 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -typedef struct Foo { - int a; -}Foo; - -typedef struct Bar { - int a; -}Bar; - -int Foo::getA(int b, struct Foo* this) { // expected-error {{'this' cannot be the name of a parameter}} - return this->a; -} - -int Foo::getBarA(struct Bar* this) { // expected-error {{struct Bar * is not supported on this target}} - return this->a; -} \ No newline at end of file diff --git a/clang/test/BSC/pending/ThisParamCheck2.cbs b/clang/test/BSC/pending/ThisParamCheck2.cbs deleted file mode 100644 index 1fee3762a580..000000000000 --- a/clang/test/BSC/pending/ThisParamCheck2.cbs +++ /dev/null @@ -1,21 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -typedef struct Foo{ - int a; -}Foo; - -int Foo::s1() { - return 1; -} - -int Foo::s2(struct Foo* other) { - return other->a; -} - -int main() { - struct Foo x = {0}; - x.s1(); // expected-error {{no member named 's1' in 'struct Foo'; did you mean to use '::' instead of '.'?}} - - x.s2(); // expected-error {{no member named 's2' in 'struct Foo'; did you mean to use '::' instead of '.'?}} - return 0; -} \ No newline at end of file -- Gitee