//===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===// // // 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 semantic analysis for expressions involving // pseudo-object references. Pseudo-objects are conceptual objects // whose storage is entirely abstract and all accesses to which are // translated through some sort of abstraction barrier. // // For example, Objective-C objects can have "properties", either // declared or undeclared. A property may be accessed by writing // expr.prop // where 'expr' is an r-value of Objective-C pointer type and 'prop' // is the name of the property. If this expression is used in a context // needing an r-value, it is treated as if it were a message-send // of the associated 'getter' selector, typically: // [expr prop] // If it is used as the LHS of a simple assignment, it is treated // as a message-send of the associated 'setter' selector, typically: // [expr setProp: RHS] // If it is used as the LHS of a compound assignment, or the operand // of a unary increment or decrement, both are required; for example, // 'expr.prop *= 100' would be translated to: // [expr setProp: [expr prop] * 100] // //===----------------------------------------------------------------------===// #include "clang/Sema/SemaPseudoObject.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/Basic/CharInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "llvm/ADT/SmallString.h" usingnamespaceclang; usingnamespacesema; namespace { // Basically just a very focused copy of TreeTransform. struct Rebuilder { … }; class PseudoOpBuilder { … }; /// A PseudoOpBuilder for Objective-C \@properties. class ObjCPropertyOpBuilder : public PseudoOpBuilder { … }; /// A PseudoOpBuilder for Objective-C array/dictionary indexing. class ObjCSubscriptOpBuilder : public PseudoOpBuilder { … }; class MSPropertyOpBuilder : public PseudoOpBuilder { … }; } /// Capture the given expression in an OpaqueValueExpr. OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) { … } /// Capture the given expression as the result of this pseudo-object /// operation. This routine is safe against expressions which may /// already be captured. /// /// \returns the captured expression, which will be the /// same as the input if the input was already captured OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) { … } /// The routine which creates the final PseudoObjectExpr. ExprResult PseudoOpBuilder::complete(Expr *syntactic) { … } /// The main skeleton for building an r-value operation. ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) { … } /// The basic skeleton for building a simple or compound /// assignment operation. ExprResult PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, BinaryOperatorKind opcode, Expr *LHS, Expr *RHS) { … } /// The basic skeleton for building an increment or decrement /// operation. ExprResult PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, UnaryOperatorKind opcode, Expr *op) { … } //===----------------------------------------------------------------------===// // Objective-C @property and implicit property references //===----------------------------------------------------------------------===// /// Look up a method in the receiver type of an Objective-C property /// reference. static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel, const ObjCPropertyRefExpr *PRE) { … } bool ObjCPropertyOpBuilder::isWeakProperty() const { … } bool ObjCPropertyOpBuilder::findGetter() { … } /// Try to find the most accurate setter declaration for the property /// reference. /// /// \return true if a setter was found, in which case Setter bool ObjCPropertyOpBuilder::findSetter(bool warn) { … } void ObjCPropertyOpBuilder::DiagnoseUnsupportedPropertyUse() { … } /// Capture the base object of an Objective-C property expression. Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { … } /// Load from an Objective-C property reference. ExprResult ObjCPropertyOpBuilder::buildGet() { … } /// Store to an Objective-C property reference. /// /// \param captureSetValueAsResult If true, capture the actual /// value being set as the value of the property operation. ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, bool captureSetValueAsResult) { … } /// @property-specific behavior for doing lvalue-to-rvalue conversion. ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { … } /// Try to build this as a call to a getter that returns a reference. /// /// \return true if it was possible, whether or not it actually /// succeeded bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op, ExprResult &result) { … } /// @property-specific behavior for doing assignments. ExprResult ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, BinaryOperatorKind opcode, Expr *LHS, Expr *RHS) { … } /// @property-specific behavior for doing increments and decrements. ExprResult ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, UnaryOperatorKind opcode, Expr *op) { … } ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) { … } // ObjCSubscript build stuff. // /// objective-c subscripting-specific behavior for doing lvalue-to-rvalue /// conversion. /// FIXME. Remove this routine if it is proven that no additional /// specifity is needed. ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) { … } /// objective-c subscripting-specific behavior for doing assignments. ExprResult ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, BinaryOperatorKind opcode, Expr *LHS, Expr *RHS) { … } /// Capture the base object of an Objective-C Index'ed expression. Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { … } /// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF /// objects used as dictionary subscript key objects. static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT, Expr *Key) { … } bool ObjCSubscriptOpBuilder::findAtIndexGetter() { … } bool ObjCSubscriptOpBuilder::findAtIndexSetter() { … } // Get the object at "Index" position in the container. // [BaseExpr objectAtIndexedSubscript : IndexExpr]; ExprResult ObjCSubscriptOpBuilder::buildGet() { … } /// Store into the container the "op" object at "Index"'ed location /// by building this messaging expression: /// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; /// \param captureSetValueAsResult If true, capture the actual /// value being set as the value of the property operation. ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, bool captureSetValueAsResult) { … } //===----------------------------------------------------------------------===// // MSVC __declspec(property) references //===----------------------------------------------------------------------===// MSPropertyRefExpr * MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) { … } Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { … } ExprResult MSPropertyOpBuilder::buildGet() { … } ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl, bool captureSetValueAsResult) { … } //===----------------------------------------------------------------------===// // General Sema routines. //===----------------------------------------------------------------------===// ExprResult SemaPseudoObject::checkRValue(Expr *E) { … } /// Check an increment or decrement of a pseudo-object expression. ExprResult SemaPseudoObject::checkIncDec(Scope *Sc, SourceLocation opcLoc, UnaryOperatorKind opcode, Expr *op) { … } ExprResult SemaPseudoObject::checkAssignment(Scope *S, SourceLocation opcLoc, BinaryOperatorKind opcode, Expr *LHS, Expr *RHS) { … } /// Given a pseudo-object reference, rebuild it without the opaque /// values. Basically, undo the behavior of rebuildAndCaptureObject. /// This should never operate in-place. static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) { … } /// Given a pseudo-object expression, recreate what it looks like /// syntactically without the attendant OpaqueValueExprs. /// /// This is a hack which should be removed when TreeTransform is /// capable of rebuilding a tree without stripping implicit /// operations. Expr *SemaPseudoObject::recreateSyntacticForm(PseudoObjectExpr *E) { … } SemaPseudoObject::SemaPseudoObject(Sema &S) : … { … }