//===--- ParseObjC.cpp - Objective C Parsing ------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements the Objective-C portions of the Parser interface. // //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ODRDiagsEmitter.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/TargetInfo.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaCodeCompletion.h" #include "clang/Sema/SemaObjC.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" usingnamespaceclang; /// Skips attributes after an Objective-C @ directive. Emits a diagnostic. void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) { … } /// ParseObjCAtDirectives - Handle parts of the external-declaration production: /// external-declaration: [C99 6.9] /// [OBJC] objc-class-definition /// [OBJC] objc-class-declaration /// [OBJC] objc-alias-declaration /// [OBJC] objc-protocol-definition /// [OBJC] objc-method-definition /// [OBJC] '@' 'end' Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives(ParsedAttributes &DeclAttrs, ParsedAttributes &DeclSpecAttrs) { … } /// Class to handle popping type parameters when leaving the scope. class Parser::ObjCTypeParamListScope { … }; /// /// objc-class-declaration: /// '@' 'class' objc-class-forward-decl (',' objc-class-forward-decl)* ';' /// /// objc-class-forward-decl: /// identifier objc-type-parameter-list[opt] /// Parser::DeclGroupPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { … } void Parser::CheckNestedObjCContexts(SourceLocation AtLoc) { … } /// /// objc-interface: /// objc-class-interface-attributes[opt] objc-class-interface /// objc-category-interface /// /// objc-class-interface: /// '@' 'interface' identifier objc-type-parameter-list[opt] /// objc-superclass[opt] objc-protocol-refs[opt] /// objc-class-instance-variables[opt] /// objc-interface-decl-list /// @end /// /// objc-category-interface: /// '@' 'interface' identifier objc-type-parameter-list[opt] /// '(' identifier[opt] ')' objc-protocol-refs[opt] /// objc-interface-decl-list /// @end /// /// objc-superclass: /// ':' identifier objc-type-arguments[opt] /// /// objc-class-interface-attributes: /// __attribute__((visibility("default"))) /// __attribute__((visibility("hidden"))) /// __attribute__((deprecated)) /// __attribute__((unavailable)) /// __attribute__((objc_exception)) - used by NSException on 64-bit /// __attribute__((objc_root_class)) /// Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, ParsedAttributes &attrs) { … } /// Add an attribute for a context-sensitive type nullability to the given /// declarator. static void addContextSensitiveTypeNullability(Parser &P, Declarator &D, NullabilityKind nullability, SourceLocation nullabilityLoc, bool &addedToDeclSpec) { … } /// Parse an Objective-C type parameter list, if present, or capture /// the locations of the protocol identifiers for a list of protocol /// references. /// /// objc-type-parameter-list: /// '<' objc-type-parameter (',' objc-type-parameter)* '>' /// /// objc-type-parameter: /// objc-type-parameter-variance? identifier objc-type-parameter-bound[opt] /// /// objc-type-parameter-bound: /// ':' type-name /// /// objc-type-parameter-variance: /// '__covariant' /// '__contravariant' /// /// \param lAngleLoc The location of the starting '<'. /// /// \param protocolIdents Will capture the list of identifiers, if the /// angle brackets contain a list of protocol references rather than a /// type parameter list. /// /// \param rAngleLoc The location of the ending '>'. ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc, SmallVectorImpl<IdentifierLocPair> &protocolIdents, SourceLocation &rAngleLoc, bool mayBeProtocolList) { … } /// Parse an objc-type-parameter-list. ObjCTypeParamList *Parser::parseObjCTypeParamList() { … } static bool isTopLevelObjCKeyword(tok::ObjCKeywordKind DirectiveKind) { … } /// objc-interface-decl-list: /// empty /// objc-interface-decl-list objc-property-decl [OBJC2] /// objc-interface-decl-list objc-method-requirement [OBJC2] /// objc-interface-decl-list objc-method-proto ';' /// objc-interface-decl-list declaration /// objc-interface-decl-list ';' /// /// objc-method-requirement: [OBJC2] /// @required /// @optional /// void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, Decl *CDecl) { … } /// Diagnose redundant or conflicting nullability information. static void diagnoseRedundantPropertyNullability(Parser &P, ObjCDeclSpec &DS, NullabilityKind nullability, SourceLocation nullabilityLoc){ … } /// Parse property attribute declarations. /// /// property-attr-decl: '(' property-attrlist ')' /// property-attrlist: /// property-attribute /// property-attrlist ',' property-attribute /// property-attribute: /// getter '=' identifier /// setter '=' identifier ':' /// direct /// readonly /// readwrite /// assign /// retain /// copy /// nonatomic /// atomic /// strong /// weak /// unsafe_unretained /// nonnull /// nullable /// null_unspecified /// null_resettable /// class /// void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { … } /// objc-method-proto: /// objc-instance-method objc-method-decl objc-method-attributes[opt] /// objc-class-method objc-method-decl objc-method-attributes[opt] /// /// objc-instance-method: '-' /// objc-class-method: '+' /// /// objc-method-attributes: [OBJC2] /// __attribute__((deprecated)) /// Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind, bool MethodDefinition) { … } /// objc-selector: /// identifier /// one of /// enum struct union if else while do for switch case default /// break continue return goto asm sizeof typeof __alignof /// unsigned long const short volatile signed restrict _Complex /// in out inout bycopy byref oneway int char float double void _Bool /// IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) { … } /// objc-for-collection-in: 'in' /// bool Parser::isTokIdentifier_in() const { … } /// ParseObjCTypeQualifierList - This routine parses the objective-c's type /// qualifier list and builds their bitmask representation in the input /// argument. /// /// objc-type-qualifiers: /// objc-type-qualifier /// objc-type-qualifiers objc-type-qualifier /// /// objc-type-qualifier: /// 'in' /// 'out' /// 'inout' /// 'oneway' /// 'bycopy' /// 'byref' /// 'nonnull' /// 'nullable' /// 'null_unspecified' /// void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, DeclaratorContext Context) { … } /// Take all the decl attributes out of the given list and add /// them to the given attribute set. static void takeDeclAttributes(ParsedAttributesView &attrs, ParsedAttributesView &from) { … } /// takeDeclAttributes - Take all the decl attributes from the given /// declarator and add them to the given list. static void takeDeclAttributes(ParsedAttributes &attrs, Declarator &D) { … } /// objc-type-name: /// '(' objc-type-qualifiers[opt] type-name ')' /// '(' objc-type-qualifiers[opt] ')' /// ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, DeclaratorContext context, ParsedAttributes *paramAttrs) { … } /// objc-method-decl: /// objc-selector /// objc-keyword-selector objc-parmlist[opt] /// objc-type-name objc-selector /// objc-type-name objc-keyword-selector objc-parmlist[opt] /// /// objc-keyword-selector: /// objc-keyword-decl /// objc-keyword-selector objc-keyword-decl /// /// objc-keyword-decl: /// objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier /// objc-selector ':' objc-keyword-attributes[opt] identifier /// ':' objc-type-name objc-keyword-attributes[opt] identifier /// ':' objc-keyword-attributes[opt] identifier /// /// objc-parmlist: /// objc-parms objc-ellipsis[opt] /// /// objc-parms: /// objc-parms , parameter-declaration /// /// objc-ellipsis: /// , ... /// /// objc-keyword-attributes: [OBJC2] /// __attribute__((unused)) /// Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, tok::ObjCKeywordKind MethodImplKind, bool MethodDefinition) { … } /// objc-protocol-refs: /// '<' identifier-list '>' /// bool Parser:: ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, SmallVectorImpl<SourceLocation> &ProtocolLocs, bool WarnOnDeclarations, bool ForObjCContainer, SourceLocation &LAngleLoc, SourceLocation &EndLoc, bool consumeLastToken) { … } TypeResult Parser::parseObjCProtocolQualifierType(SourceLocation &rAngleLoc) { … } /// Parse Objective-C type arguments or protocol qualifiers. /// /// objc-type-arguments: /// '<' type-name '...'[opt] (',' type-name '...'[opt])* '>' /// void Parser::parseObjCTypeArgsOrProtocolQualifiers( ParsedType baseType, SourceLocation &typeArgsLAngleLoc, SmallVectorImpl<ParsedType> &typeArgs, SourceLocation &typeArgsRAngleLoc, SourceLocation &protocolLAngleLoc, SmallVectorImpl<Decl *> &protocols, SmallVectorImpl<SourceLocation> &protocolLocs, SourceLocation &protocolRAngleLoc, bool consumeLastToken, bool warnOnIncompleteProtocols) { … } void Parser::parseObjCTypeArgsAndProtocolQualifiers( ParsedType baseType, SourceLocation &typeArgsLAngleLoc, SmallVectorImpl<ParsedType> &typeArgs, SourceLocation &typeArgsRAngleLoc, SourceLocation &protocolLAngleLoc, SmallVectorImpl<Decl *> &protocols, SmallVectorImpl<SourceLocation> &protocolLocs, SourceLocation &protocolRAngleLoc, bool consumeLastToken) { … } TypeResult Parser::parseObjCTypeArgsAndProtocolQualifiers( SourceLocation loc, ParsedType type, bool consumeLastToken, SourceLocation &endLoc) { … } void Parser::HelperActionsForIvarDeclarations( ObjCContainerDecl *interfaceDecl, SourceLocation atLoc, BalancedDelimiterTracker &T, SmallVectorImpl<Decl *> &AllIvarDecls, bool RBraceMissing) { … } /// objc-class-instance-variables: /// '{' objc-instance-variable-decl-list[opt] '}' /// /// objc-instance-variable-decl-list: /// objc-visibility-spec /// objc-instance-variable-decl ';' /// ';' /// objc-instance-variable-decl-list objc-visibility-spec /// objc-instance-variable-decl-list objc-instance-variable-decl ';' /// objc-instance-variable-decl-list static_assert-declaration /// objc-instance-variable-decl-list ';' /// /// objc-visibility-spec: /// @private /// @protected /// @public /// @package [OBJC2] /// /// objc-instance-variable-decl: /// struct-declaration /// void Parser::ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl, tok::ObjCKeywordKind visibility, SourceLocation atLoc) { … } /// objc-protocol-declaration: /// objc-protocol-definition /// objc-protocol-forward-reference /// /// objc-protocol-definition: /// \@protocol identifier /// objc-protocol-refs[opt] /// objc-interface-decl-list /// \@end /// /// objc-protocol-forward-reference: /// \@protocol identifier-list ';' /// /// "\@protocol identifier ;" should be resolved as "\@protocol /// identifier-list ;": objc-interface-decl-list may not start with a /// semicolon in the first alternative if objc-protocol-refs are omitted. Parser::DeclGroupPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, ParsedAttributes &attrs) { … } /// objc-implementation: /// objc-class-implementation-prologue /// objc-category-implementation-prologue /// /// objc-class-implementation-prologue: /// @implementation identifier objc-superclass[opt] /// objc-class-instance-variables[opt] /// /// objc-category-implementation-prologue: /// @implementation identifier ( identifier ) Parser::DeclGroupPtrTy Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc, ParsedAttributes &Attrs) { … } Parser::DeclGroupPtrTy Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { … } Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() { … } void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) { … } /// compatibility-alias-decl: /// @compatibility_alias alias-name class-name ';' /// Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) { … } /// property-synthesis: /// @synthesize property-ivar-list ';' /// /// property-ivar-list: /// property-ivar /// property-ivar-list ',' property-ivar /// /// property-ivar: /// identifier /// identifier '=' identifier /// Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { … } /// property-dynamic: /// @dynamic property-list /// /// property-list: /// identifier /// property-list ',' identifier /// Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { … } /// objc-throw-statement: /// throw expression[opt]; /// StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) { … } /// objc-synchronized-statement: /// @synchronized '(' expression ')' compound-statement /// StmtResult Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { … } /// objc-try-catch-statement: /// @try compound-statement objc-catch-list[opt] /// @try compound-statement objc-catch-list[opt] @finally compound-statement /// /// objc-catch-list: /// @catch ( parameter-declaration ) compound-statement /// objc-catch-list @catch ( catch-parameter-declaration ) compound-statement /// catch-parameter-declaration: /// parameter-declaration /// '...' [OBJC2] /// StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { … } /// objc-autoreleasepool-statement: /// @autoreleasepool compound-statement /// StmtResult Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) { … } /// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them /// for later parsing. void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) { … } /// objc-method-def: objc-method-proto ';'[opt] '{' body '}' /// Decl *Parser::ParseObjCMethodDefinition() { … } StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc, ParsedStmtContext StmtCtx) { … } ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { … } /// Parse the receiver of an Objective-C++ message send. /// /// This routine parses the receiver of a message send in /// Objective-C++ either as a type or as an expression. Note that this /// routine must not be called to parse a send to 'super', since it /// has no way to return such a result. /// /// \param IsExpr Whether the receiver was parsed as an expression. /// /// \param TypeOrExpr If the receiver was parsed as an expression (\c /// IsExpr is true), the parsed expression. If the receiver was parsed /// as a type (\c IsExpr is false), the parsed type. /// /// \returns True if an error occurred during parsing or semantic /// analysis, in which case the arguments do not have valid /// values. Otherwise, returns false for a successful parse. /// /// objc-receiver: [C++] /// 'super' [not parsed here] /// expression /// simple-type-specifier /// typename-specifier bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { … } /// Determine whether the parser is currently referring to a an /// Objective-C message send, using a simplified heuristic to avoid overhead. /// /// This routine will only return true for a subset of valid message-send /// expressions. bool Parser::isSimpleObjCMessageExpression() { … } bool Parser::isStartOfObjCClassMessageMissingOpenBracket() { … } /// objc-message-expr: /// '[' objc-receiver objc-message-args ']' /// /// objc-receiver: [C] /// 'super' /// expression /// class-name /// type-name /// ExprResult Parser::ParseObjCMessageExpression() { … } /// Parse the remainder of an Objective-C message following the /// '[' objc-receiver. /// /// This routine handles sends to super, class messages (sent to a /// class name), and instance messages (sent to an object), and the /// target is represented by \p SuperLoc, \p ReceiverType, or \p /// ReceiverExpr, respectively. Only one of these parameters may have /// a valid value. /// /// \param LBracLoc The location of the opening '['. /// /// \param SuperLoc If this is a send to 'super', the location of the /// 'super' keyword that indicates a send to the superclass. /// /// \param ReceiverType If this is a class message, the type of the /// class we are sending a message to. /// /// \param ReceiverExpr If this is an instance message, the expression /// used to compute the receiver object. /// /// objc-message-args: /// objc-selector /// objc-keywordarg-list /// /// objc-keywordarg-list: /// objc-keywordarg /// objc-keywordarg-list objc-keywordarg /// /// objc-keywordarg: /// selector-name[opt] ':' objc-keywordexpr /// /// objc-keywordexpr: /// nonempty-expr-list /// /// nonempty-expr-list: /// assignment-expression /// nonempty-expr-list , assignment-expression /// ExprResult Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, SourceLocation SuperLoc, ParsedType ReceiverType, Expr *ReceiverExpr) { … } ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { … } /// ParseObjCBooleanLiteral - /// objc-scalar-literal : '@' boolean-keyword /// ; /// boolean-keyword: 'true' | 'false' | '__objc_yes' | '__objc_no' /// ; ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc, bool ArgValue) { … } /// ParseObjCCharacterLiteral - /// objc-scalar-literal : '@' character-literal /// ; ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) { … } /// ParseObjCNumericLiteral - /// objc-scalar-literal : '@' scalar-literal /// ; /// scalar-literal : | numeric-constant /* any numeric constant. */ /// ; ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) { … } /// ParseObjCBoxedExpr - /// objc-box-expression: /// @( assignment-expression ) ExprResult Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) { … } ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { … } ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { … } /// objc-encode-expression: /// \@encode ( type-name ) ExprResult Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) { … } /// objc-protocol-expression /// \@protocol ( protocol-name ) ExprResult Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { … } /// objc-selector-expression /// @selector '(' '('[opt] objc-keyword-selector ')'[opt] ')' ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { … } void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { … }