diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index b19f98326eeba639d34e741d20bb446fd170ed0d..c327014732ef9cc96d2ec1e0588e3f2e90c77003 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -138,7 +138,7 @@ protected: friend class ASTStmtReader; // Sets dependence dircetly. public: - bool HasBSCScopeSpce = false; + bool HasBSCScopeSpec = 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 3f6dc67f257ca42f0e04c748c878702348fe26c7..9e800892644710a8c1359772ca46d596bcbb3dfc 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1787,14 +1787,17 @@ private: UnaryExprOnly, PrimaryExprOnly }; + ExprResult ParseOptionalBSCScopeSpecifier( + CastParseKind ParseKind, bool isAddressOfOperand, bool &NotCastExpr, + TypeCastState isTypeCast, bool isVectorLiteral = false, + bool *NotPrimaryExpression = nullptr, bool HasBSCScopeSpec = false); ExprResult ParseCastExpression(CastParseKind ParseKind, - bool isAddressOfOperand, - bool &NotCastExpr, + bool isAddressOfOperand, bool &NotCastExpr, TypeCastState isTypeCast, bool isVectorLiteral = false, bool *NotPrimaryExpression = nullptr, QualType T = QualType(), - bool HasBSCScopeSpce = false); + bool HasBSCScopeSpec = false); ExprResult ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand = false, TypeCastState isTypeCast = NotTypeCast, diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 6fb1a7dba79a080a9795a938745fc977705cd2f0..22b280decae4718b41f9019c0d83a4d4b33f9149 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -729,6 +729,26 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback { }; } +ExprResult Parser::ParseOptionalBSCScopeSpecifier( + CastParseKind ParseKind, bool isAddressOfOperand, bool &NotCastExpr, + TypeCastState isTypeCast, bool isVectorLiteral, bool *NotPrimaryExpression, + bool HasBSCScopeSpec) { + 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 + HasBSCScopeSpec = TryConsumeToken(tok::coloncolon); + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_expected_unqualified_id) << 0; + return ExprError(); + } + return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, + isTypeCast, isVectorLiteral, NotPrimaryExpression, + T, HasBSCScopeSpec); +} + /// Parse a cast-expression, or, if \pisUnaryExpression is true, parse /// a unary-expression. /// @@ -913,7 +933,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, bool &NotCastExpr, TypeCastState isTypeCast, bool isVectorLiteral, bool *NotPrimaryExpression, - QualType T, bool HasBSCScopeSpce) { + QualType T, bool HasBSCScopeSpec) { ExprResult Res; tok::TokenKind SavedKind = Tok.getKind(); auto SavedType = PreferredType; @@ -1039,16 +1059,9 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, 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); + return ParseOptionalBSCScopeSpecifier( + ParseKind, isAddressOfOperand, NotCastExpr, isTypeCast, + isVectorLiteral, NotPrimaryExpression, HasBSCScopeSpec); } // Fall through; this isn't a message send. LLVM_FALLTHROUGH; @@ -1056,16 +1069,9 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, // 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); + return ParseOptionalBSCScopeSpecifier( + ParseKind, isAddressOfOperand, NotCastExpr, isTypeCast, + isVectorLiteral, NotPrimaryExpression, HasBSCScopeSpec); } // Turn a potentially qualified name into a annot_typename or // annot_cxxscope if it would be valid. This handles things like x::y, etc. @@ -1553,16 +1559,9 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, #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); + return ParseOptionalBSCScopeSpecifier( + ParseKind, isAddressOfOperand, NotCastExpr, isTypeCast, + isVectorLiteral, NotPrimaryExpression, HasBSCScopeSpec); } if (!getLangOpts().CPlusPlus) { Diag(Tok, diag::err_expected_expression); @@ -1846,7 +1845,7 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, // These can be followed by postfix-expr pieces. PreferredType = SavedType; if (Res.get()) - Res.get()->HasBSCScopeSpce = HasBSCScopeSpce; + Res.get()->HasBSCScopeSpec = HasBSCScopeSpec; Res = ParsePostfixExpressionSuffix(Res); if (getLangOpts().OpenCL) if (Expr *PostfixExpr = Res.get()) { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8843c1f8d082d90ac3d647d46ec47d36604909db..4dce16017717a0a306be0212782ec078480b3a64 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5785,7 +5785,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, : (IsExecConfig ? 3 /* kernel function (exec config) */ : 0 /* function */); bool isBSCInstanceFunc = false; - if (FDecl && !Fn->HasBSCScopeSpce) { + if (FDecl && !Fn->HasBSCScopeSpec) { BSCMethodDecl* MD = dyn_cast_or_null(FDecl); if (MD && MD->getHasThisParam()) { isBSCInstanceFunc = true; @@ -6621,7 +6621,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, ArrayRef Args, SourceLocation RParenLoc, Expr *Config, bool IsExecConfig, ADLCallKind UsesADL) { - bool HasBSCScopeSpce = Fn->HasBSCScopeSpce; + bool HasBSCScopeSpec = Fn->HasBSCScopeSpec; FunctionDecl *FDecl = dyn_cast_or_null(NDecl); unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0); @@ -6663,7 +6663,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (Result.isInvalid()) return ExprError(); Fn = Result.get(); - Fn->HasBSCScopeSpce = HasBSCScopeSpce; + Fn->HasBSCScopeSpec = HasBSCScopeSpec; // 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/test/BSC/Method/Struct/struct_no_function_name.cbs b/clang/test/BSC/Method/Struct/struct_no_function_name.cbs new file mode 100644 index 0000000000000000000000000000000000000000..b6326de9e866e70ba450f1eff5cd7c74e24518a1 --- /dev/null +++ b/clang/test/BSC/Method/Struct/struct_no_function_name.cbs @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +struct Foo { + int a; +}; + +int main() { + struct Foo foo = {.a = 1}; + int a = struct Foo::(&foo); // expected-error {{expected identifier}} + return a - 1; +} \ No newline at end of file