Go to the documentation of this file.
25 #include "llvm/ADT/StringSwitch.h"
26 #include "llvm/Support/Debug.h"
28 #define DEBUG_TYPE "body-farm"
30 using namespace clang;
66 bool RefersToEnclosingVariableOrCapture =
false);
84 bool RefersToEnclosingVariableOrCapture =
false);
107 bool IsArrow =
false,
122 C,
const_cast<Expr *
>(LHS),
const_cast<Expr *
>(RHS), BO_Assign, Ty,
131 C,
const_cast<Expr *
>(LHS),
const_cast<Expr *
>(RHS), Op,
142 bool RefersToEnclosingVariableOrCapture) {
158 return makeImplicitCast(Arg, Ty, CK_LValueToRValue);
162 ASTMaker::makeLvalueToRvalue(
const VarDecl *Arg,
163 bool RefersToEnclosingVariableOrCapture) {
165 return makeLvalueToRvalue(makeDeclRefExpr(Arg,
166 RefersToEnclosingVariableOrCapture),
174 const_cast<Expr *
>(Arg),
185 const_cast<Expr *
>(Arg),
nullptr,
192 return const_cast<Expr*
>(Arg);
193 return makeImplicitCast(Arg, Ty, CK_IntegralCast);
197 return makeImplicitCast(Arg,
C.BoolTy, CK_IntegralToBoolean);
201 QualType Ty =
C.getBOOLDecl() ?
C.getBOOLType() :
C.ObjCBuiltinBoolTy;
232 nullptr, MemberDecl->
getType(), ValueKind,
248 return cast<ValueDecl>(FoundDecl);
267 SubExpr = M.makeImplicitCast(
270 Call->getType()->isFunctionType()) {
272 SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay);
274 && Call->getType()->isPointerType()
275 && Call->getType()->getPointeeType()->isFunctionType()){
278 llvm_unreachable(
"Unexpected state");
289 assert(CallbackDecl !=
nullptr);
292 assert(callOperatorDecl !=
nullptr);
305 C, OO_Call, callOperatorDeclRef,
319 LLVM_DEBUG(llvm::dbgs() <<
"Generating body for std::move / std::forward\n");
325 Expr *
Cast = M.makeReferenceCast(Param, ReturnType);
326 return M.makeReturn(
Cast);
345 LLVM_DEBUG(llvm::dbgs() <<
"Generating body for call_once\n");
356 if (!Callback->getType()->isReferenceType()) {
357 llvm::dbgs() <<
"libcxx03 std::call_once implementation, skipping.\n";
361 llvm::dbgs() <<
"unknown std::call_once implementation, skipping.\n";
365 QualType CallbackType = Callback->getType().getNonReferenceType();
372 if (!FlagRecordDecl) {
373 LLVM_DEBUG(llvm::dbgs() <<
"Flag field is not a record: "
374 <<
"unknown std::call_once implementation, "
375 <<
"ignoring the call.\n");
381 ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl,
"__state_");
385 if (!FlagFieldDecl) {
386 FlagFieldDecl = M.findMemberField(FlagRecordDecl,
"_M_once");
389 if (!FlagFieldDecl) {
390 LLVM_DEBUG(llvm::dbgs() <<
"No field _M_once or __state_ found on "
391 <<
"std::once_flag struct: unknown std::call_once "
392 <<
"implementation, ignoring the call.");
396 bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->
isLambda();
397 if (CallbackRecordDecl && !isLambdaCall) {
398 LLVM_DEBUG(llvm::dbgs()
399 <<
"Not supported: synthesizing body for functors when "
400 <<
"body farming std::call_once, ignoring the call.");
410 M.makeDeclRefExpr(Callback,
416 CallbackFunctionType =
422 if (!CallbackFunctionType)
427 LLVM_DEBUG(llvm::dbgs() <<
"Types of params of the callback do not match "
428 <<
"params passed to std::call_once, "
429 <<
"ignoring the call\n");
443 LLVM_DEBUG(llvm::dbgs() <<
"Types of params of the callback do not match "
444 <<
"params passed to std::call_once, "
445 <<
"ignoring the call\n");
448 Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
451 ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
453 CallArgs.push_back(ParamExpr);
460 CallbackRecordDecl, CallArgs);
468 M.makeDeclRefExpr(Flag,
472 MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl);
473 assert(Deref->isLValue());
474 QualType DerefType = Deref->getType();
480 M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
481 CK_IntegralToBoolean),
490 Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.IntTy), DerefType),
500 M.makeCompound({CallbackCall, FlagAssignment}));
542 M.makeLvalueToRvalue(
Block),
557 M.makeLvalueToRvalue(
558 M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
560 M.makeIntegralCast(DoneValue, PredicateTy),
564 Stmt *Stmts[] = { B, CE };
569 M.makeLvalueToRvalue(
571 M.makeLvalueToRvalue(
572 M.makeDeclRefExpr(Predicate),
577 Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE);
644 assert(OldValueTy == NewValueTy);
657 M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
658 M.makeLvalueToRvalue(
660 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
670 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
672 M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
675 Expr *BoolVal = M.makeObjCBool(
true);
676 Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
677 : M.makeIntegralCast(BoolVal, ResultTy);
678 Stmts[1] = M.makeReturn(RetVal);
682 BoolVal = M.makeObjCBool(
false);
683 RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
684 : M.makeIntegralCast(BoolVal, ResultTy);
685 Stmt *Else = M.makeReturn(RetVal);
701 return Val.getValue();
716 case Builtin::BIas_const:
717 case Builtin::BIforward:
718 case Builtin::BImove:
719 case Builtin::BImove_if_noexcept:
726 }
else if (Name.startswith(
"OSAtomicCompareAndSwap") ||
727 Name.startswith(
"objc_atomicCompareAndSwap")) {
732 FF = llvm::StringSwitch<FunctionFarmer>(Name)
738 if (FF) { Val = FF(C, D); }
739 else if (Injector) { Val = Injector->
getBody(D); }
740 return Val.getValue();
758 auto *Container = cast<ObjCContainerDecl>(Prop->
getDeclContext());
760 if (
auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
761 PrimaryInterface = InterfaceDecl;
762 }
else if (
auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
763 PrimaryInterface = CategoryDecl->getClassInterface();
764 }
else if (
auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
765 PrimaryInterface = ImplDecl->getClassInterface();
775 if (ShadowingProp && ShadowingProp != Prop) {
776 IVar = ShadowingProp->getPropertyIvarDecl();
796 if (Candidate->getGetterName() == MD->
getSelector()) {
825 if (I->getPropertyDecl() != Prop)
828 if (I->getGetterCXXConstructor()) {
830 return M.makeReturn(I->getGetterCXXConstructor());
852 Expr *loadedIVar = M.makeObjCIvarRef(
853 M.makeLvalueToRvalue(M.makeDeclRefExpr(selfVar), selfVar->
getType()),
857 loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->
getType());
859 return M.makeReturn(loadedIVar);
876 return Val.getValue();
894 if (dyn_cast<ObjCInterfaceDecl>(D->
getParent()) != OID)
897 if (OMD && !OMD->isImplicit())
903 return Val.getValue();
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Represents an ObjC class declaration.
bool isReadOnly() const
isReadOnly - Return true iff the property has a setter.
virtual Stmt * getBody(const FunctionDecl *D)=0
static IfStmt * Create(const ASTContext &Ctx, SourceLocation IL, IfStatementKind Kind, Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LPL, SourceLocation RPL, Stmt *Then, SourceLocation EL=SourceLocation(), Stmt *Else=nullptr)
Create an IfStmt.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
@ OK_Ordinary
An ordinary object is located at an address in memory.
QualType getReturnType() const
A trivial tuple used to represent a source range.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Encodes a location in the source.
This represents a decl that may have a name.
static MemberExpr * Create(const ASTContext &C, Expr *Base, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, DeclAccessPair FoundDecl, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR)
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
A (possibly-)qualified type.
const ParmVarDecl * getParamDecl(unsigned i) const
static CXXStaticCastExpr * Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *Path, TypeSourceInfo *Written, FPOptionsOverride FPO, SourceLocation L, SourceLocation RParenLoc, SourceRange AngleBrackets)
QualType getCanonicalType() const
Represents a parameter to a function.
@ VK_XValue
An x-value expression is a reference to an object with independent storage but which can be "moved",...
static bool isDispatchBlock(QualType Ty)
ObjCInterfaceDecl * getClassInterface()
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
bool isRValueReferenceType() const
FunctionType - C99 6.7.5.3 - Function Declarators.
size_t param_size() const
The name of a declaration.
known_extensions_range known_extensions() const
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
The base class of the type hierarchy.
ObjCBoolLiteralExpr - Objective-C Boolean Literal.
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
bool isReferenceType() const
static ReturnStmt * Create(const ASTContext &Ctx, SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
Create a return statement.
static const ObjCIvarDecl * findBackingIvar(const ObjCPropertyDecl *Prop)
CompoundStmt - This represents a group of statements like { stmt stmt }.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Stmt *(* FunctionFarmer)(ASTContext &C, const FunctionDecl *D)
ObjCImplementationDecl * getImplementation() const
A builtin binary operation expression such as "x + y" or "x <= y".
A POD class for pairing a NamedDecl* with an access specifier.
A single parameter index whose accessors require each use to make explicit the parameter index encodi...
Represents difference between two FPOptions values.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const T * getAs() const
Member-template getAs<specific type>'.
Selector getSelector() const
QualType getParamType(unsigned i) const
ImplicitParamDecl * getSelfDecl() const
static Stmt * createObjCPropertyGetter(ASTContext &Ctx, const ObjCMethodDecl *MD)
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
bool isLValueReferenceType() const
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
bool isStdNamespace() const
bool Cast(InterpState &S, CodePtr OpPC)
Represents a variable declaration or definition.
QualType getReturnType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
A C++ nested-name-specifier augmented with source location information.
ObjCMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
static CXXOperatorCallExpr * Create(const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation OperatorLoc, FPOptionsOverride FPFeatures, ADLCallKind UsesADL=NotADL)
bool isObjCLifetimeType() const
Returns true if objects of this type have lifetime semantics under ARC.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
const T * castAs() const
Member-template castAs<specific type>.
Represents a C++ struct/union/class.
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
propimpl_range property_impls() const
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a prototype with parameter type info, e.g.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
@ NOUR_None
This is an odr-use.
QualType getPointeeType() const
bool isSynthesizedAccessorStub() const
static Stmt * create_std_move_forward(ASTContext &C, const FunctionDecl *D)
Create a fake body for 'std::move' or 'std::forward'.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Decl - This represents one declaration (or definition), e.g.
ObjCIvarDecl * getPropertyIvarDecl() const
bool isComparisonOp() const
Represents one property declaration in an Objective-C interface.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
ObjCPropertyQueryKind getQueryKind() const
unsigned getNumParams() const
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
One of these records is kept for each identifier that is lexed.
bool isBooleanType() const
ObjCPropertyDecl * FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId, ObjCPropertyQueryKind QueryKind) const
FindPropertyVisibleInPrimaryClass - Finds declaration of the property with name 'PropertyId' in the p...
ObjCMethodDecl - Represents an instance or class method declaration.
PointerType - C99 6.7.5.1 - Pointer Declarators.
const ObjCPropertyDecl * findPropertyDecl(bool CheckOverrides=true) const
Returns the property associated with this method's selector.
ObjCMethodDecl * getInstanceMethod(Selector Sel, bool AllowHidden=false) const
static CallExpr * create_call_once_lambda_call(ASTContext &C, ASTMaker M, const ParmVarDecl *Callback, CXXRecordDecl *CallbackDecl, ArrayRef< Expr * > CallArgs)
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
Stmt - This represents one statement.
ObjCIvarDecl - Represents an ObjC instance variable.
QualType getReturnType() const
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
static Stmt * create_dispatch_sync(ASTContext &C, const FunctionDecl *D)
Create a fake body for dispatch_sync.
The results of name lookup within a DeclContext.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
bool isPropertyAccessor() const
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Stmt * getBody(const FunctionDecl *D)
Factory method for creating bodies for ordinary functions.
static CallExpr * create_call_once_funcptr_call(ASTContext &C, ASTMaker M, const ParmVarDecl *Callback, ArrayRef< Expr * > CallArgs)
QualType getPointeeType() const
bool isLambda() const
Determine whether this class describes a lambda function object.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
CastKind
CastKind - The kind of operation required for a conversion.
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const
Returns a value indicating whether this function corresponds to a builtin function.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
This represents one expression.
bool isFunctionOrMethod() const
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
ObjCPropertyAttribute::Kind getPropertyAttributes() const
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
static Stmt * create_dispatch_once(ASTContext &C, const FunctionDecl *D)
Create a fake body for dispatch_once.
static Stmt * create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
A reference to a declared variable, function, enum, etc.
Represents a function declaration or definition.
Represents a struct/union/class.
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, SourceLocation LB, SourceLocation RB)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
ObjCIvarRefExpr - A reference to an ObjC instance variable.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
unsigned param_size() const
static Stmt * create_call_once(ASTContext &C, const FunctionDecl *D)
Create a fake body for std::call_once.
DeclContext * getDeclContext()
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.