25#include "llvm/ADT/StringSwitch.h"
26#include "llvm/Support/Debug.h"
29#define DEBUG_TYPE "body-farm"
67 bool RefersToEnclosingVariableOrCapture =
false);
85 bool RefersToEnclosingVariableOrCapture =
false);
108 bool IsArrow =
false,
123 C,
const_cast<Expr *
>(LHS),
const_cast<Expr *
>(RHS), BO_Assign, Ty,
132 C,
const_cast<Expr *
>(LHS),
const_cast<Expr *
>(RHS), Op,
144 bool RefersToEnclosingVariableOrCapture) {
160 return makeImplicitCast(Arg, Ty, CK_LValueToRValue);
164ASTMaker::makeLvalueToRvalue(
const VarDecl *Arg,
165 bool RefersToEnclosingVariableOrCapture) {
167 return makeLvalueToRvalue(makeDeclRefExpr(Arg,
168 RefersToEnclosingVariableOrCapture),
176 const_cast<Expr *
>(Arg),
187 const_cast<Expr *
>(Arg),
nullptr,
194 return const_cast<Expr*
>(Arg);
195 return makeImplicitCast(Arg, Ty, CK_IntegralCast);
199 return makeImplicitCast(Arg,
C.BoolTy, CK_IntegralToBoolean);
203 QualType Ty =
C.getBOOLDecl() ?
C.getBOOLType() :
C.ObjCBuiltinBoolTy;
234 nullptr, MemberDecl->
getType(), ValueKind,
250 return cast<ValueDecl>(FoundDecl);
269 SubExpr = M.makeImplicitCast(
272 Call->getType()->isFunctionType()) {
274 SubExpr = M.makeImplicitCast(
Call, Ty, CK_FunctionToPointerDecay);
276 &&
Call->getType()->isPointerType()
277 &&
Call->getType()->getPointeeType()->isFunctionType()){
280 llvm_unreachable(
"Unexpected state");
291 assert(CallbackDecl !=
nullptr);
294 assert(callOperatorDecl !=
nullptr);
307 C, OO_Call, callOperatorDeclRef,
321 LLVM_DEBUG(llvm::dbgs() <<
"Generating body for std::move / std::forward\n");
326 Expr *Param = M.makeDeclRefExpr(
D->getParamDecl(0));
327 Expr *Cast = M.makeReferenceCast(Param, ReturnType);
328 return M.makeReturn(Cast);
347 LLVM_DEBUG(llvm::dbgs() <<
"Generating body for call_once\n");
350 if (
D->param_size() < 2)
358 if (!Callback->getType()->isReferenceType()) {
359 llvm::dbgs() <<
"libcxx03 std::call_once implementation, skipping.\n";
363 llvm::dbgs() <<
"unknown std::call_once implementation, skipping.\n";
367 QualType CallbackType = Callback->getType().getNonReferenceType();
374 if (!FlagRecordDecl) {
375 LLVM_DEBUG(llvm::dbgs() <<
"Flag field is not a record: "
376 <<
"unknown std::call_once implementation, "
377 <<
"ignoring the call.\n");
383 ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl,
"__state_");
387 if (!FlagFieldDecl) {
388 FlagFieldDecl = M.findMemberField(FlagRecordDecl,
"_M_once");
391 if (!FlagFieldDecl) {
392 LLVM_DEBUG(llvm::dbgs() <<
"No field _M_once or __state_ found on "
393 <<
"std::once_flag struct: unknown std::call_once "
394 <<
"implementation, ignoring the call.");
398 bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->
isLambda();
399 if (CallbackRecordDecl && !isLambdaCall) {
400 LLVM_DEBUG(llvm::dbgs()
401 <<
"Not supported: synthesizing body for functors when "
402 <<
"body farming std::call_once, ignoring the call.");
412 M.makeDeclRefExpr(Callback,
418 CallbackFunctionType =
424 if (!CallbackFunctionType)
428 if (
D->getNumParams() != CallbackFunctionType->
getNumParams() + 2) {
429 LLVM_DEBUG(llvm::dbgs() <<
"Types of params of the callback do not match "
430 <<
"params passed to std::call_once, "
431 <<
"ignoring the call\n");
445 LLVM_DEBUG(llvm::dbgs() <<
"Types of params of the callback do not match "
446 <<
"params passed to std::call_once, "
447 <<
"ignoring the call\n");
450 Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
453 ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
455 CallArgs.push_back(ParamExpr);
462 CallbackRecordDecl, CallArgs);
470 M.makeDeclRefExpr(Flag,
474 MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl);
475 assert(Deref->isLValue());
476 QualType DerefType = Deref->getType();
482 M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
483 CK_IntegralToBoolean),
492 Deref, M.makeIntegralCast(M.makeIntegerLiteral(1,
C.IntTy), DerefType),
502 M.makeCompound({CallbackCall, FlagAssignment}));
510 if (
D->param_size() != 2)
544 M.makeLvalueToRvalue(
Block),
559 M.makeLvalueToRvalue(
560 M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
562 M.makeIntegralCast(DoneValue, PredicateTy),
566 Stmt *Stmts[] = { B, CE };
571 M.makeLvalueToRvalue(
573 M.makeLvalueToRvalue(
574 M.makeDeclRefExpr(Predicate),
579 Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE);
594 if (
D->param_size() != 2)
621 if (
D->param_size() != 3)
646 assert(OldValueTy == NewValueTy);
659 M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
660 M.makeLvalueToRvalue(
662 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
672 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
674 M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
677 Expr *BoolVal = M.makeObjCBool(
true);
678 Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
679 : M.makeIntegralCast(BoolVal, ResultTy);
680 Stmts[1] = M.makeReturn(RetVal);
684 BoolVal = M.makeObjCBool(
false);
685 RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
686 : M.makeIntegralCast(BoolVal, ResultTy);
687 Stmt *Else = M.makeReturn(RetVal);
701 std::optional<Stmt *> &Val = Bodies[
D];
707 if (
D->getIdentifier() ==
nullptr)
710 StringRef Name =
D->getName();
716 if (
unsigned BuiltinID =
D->getBuiltinID()) {
718 case Builtin::BIas_const:
719 case Builtin::BIforward:
720 case Builtin::BIforward_like:
721 case Builtin::BImove:
722 case Builtin::BImove_if_noexcept:
729 }
else if (Name.starts_with(
"OSAtomicCompareAndSwap") ||
730 Name.starts_with(
"objc_atomicCompareAndSwap")) {
735 FF = llvm::StringSwitch<FunctionFarmer>(Name)
741 if (FF) { Val = FF(C,
D); }
742 else if (Injector) { Val = Injector->
getBody(
D); }
761 auto *Container = cast<ObjCContainerDecl>(Prop->
getDeclContext());
763 if (
auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
764 PrimaryInterface = InterfaceDecl;
765 }
else if (
auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
766 PrimaryInterface = CategoryDecl->getClassInterface();
767 }
else if (
auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
768 PrimaryInterface = ImplDecl->getClassInterface();
778 if (ShadowingProp && ShadowingProp != Prop) {
779 IVar = ShadowingProp->getPropertyIvarDecl();
799 if (Candidate->getGetterName() == MD->
getSelector()) {
828 if (
I->getPropertyDecl() != Prop)
831 if (
I->getGetterCXXConstructor()) {
833 return M.makeReturn(
I->getGetterCXXConstructor());
855 Expr *loadedIVar = M.makeObjCIvarRef(
856 M.makeLvalueToRvalue(M.makeDeclRefExpr(selfVar), selfVar->
getType()),
860 loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->
getType());
862 return M.makeReturn(loadedIVar);
867 if (!
D->isPropertyAccessor())
877 std::optional<Stmt *> &Val = Bodies[
D];
891 if (
D->param_size() != 0)
897 if (dyn_cast<ObjCInterfaceDecl>(
D->getParent()) != OID)
899 auto *OMD = Ext->getInstanceMethod(
D->getSelector());
900 if (OMD && !OMD->isImplicit())
Defines the clang::ASTContext interface.
static Stmt * create_call_once(ASTContext &C, const FunctionDecl *D)
Create a fake body for std::call_once.
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)
static Stmt * create_dispatch_sync(ASTContext &C, const FunctionDecl *D)
Create a fake body for dispatch_sync.
static Stmt * createObjCPropertyGetter(ASTContext &Ctx, const ObjCMethodDecl *MD)
static Stmt * create_std_move_forward(ASTContext &C, const FunctionDecl *D)
Create a fake body for 'std::move' or 'std::forward'.
static CallExpr * create_call_once_lambda_call(ASTContext &C, ASTMaker M, const ParmVarDecl *Callback, CXXRecordDecl *CallbackDecl, ArrayRef< Expr * > CallArgs)
static CallExpr * create_call_once_funcptr_call(ASTContext &C, ASTMaker M, const ParmVarDecl *Callback, ArrayRef< Expr * > CallArgs)
static bool isDispatchBlock(QualType Ty)
Stmt *(* FunctionFarmer)(ASTContext &C, const FunctionDecl *D)
static const ObjCIvarDecl * findBackingIvar(const ObjCPropertyDecl *Prop)
Defines enum values for all the target-independent builtin functions.
Defines the clang::CodeInjector interface which is responsible for injecting AST of function definiti...
Defines the clang::Expr interface and subclasses for C++ expressions.
Defines an enumeration for C++ overloaded operators.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
A builtin binary operation expression such as "x + y" or "x <= y".
bool isComparisonOp() const
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
QualType getPointeeType() const
Stmt * getBody(const FunctionDecl *D)
Factory method for creating bodies for ordinary functions.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
static CXXOperatorCallExpr * Create(const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation OperatorLoc, FPOptionsOverride FPFeatures, ADLCallKind UsesADL=NotADL)
Represents a C++ struct/union/class.
bool isLambda() const
Determine whether this class describes a lambda function object.
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
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)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
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.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
virtual Stmt * getBody(const FunctionDecl *D)=0
CompoundStmt - This represents a group of statements like { stmt stmt }.
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
A POD class for pairing a NamedDecl* with an access specifier.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
The results of name lookup within a DeclContext.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool isStdNamespace() const
bool isFunctionOrMethod() const
A reference to a declared variable, function, enum, etc.
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)
Decl - This represents one declaration (or definition), e.g.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
DeclContext * getDeclContext()
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
The name of a declaration.
This represents one expression.
Represents difference between two FPOptions values.
Represents a function declaration or definition.
Represents a prototype with parameter type info, e.g.
unsigned getNumParams() const
QualType getParamType(unsigned i) const
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getReturnType() const
One of these records is kept for each identifier that is lexed.
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.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
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'.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
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)
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
A C++ nested-name-specifier augmented with source location information.
ObjCBoolLiteralExpr - Objective-C Boolean Literal.
propimpl_range property_impls() const
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Represents an ObjC class declaration.
ObjCPropertyDecl * FindPropertyVisibleInPrimaryClass(const IdentifierInfo *PropertyId, ObjCPropertyQueryKind QueryKind) const
FindPropertyVisibleInPrimaryClass - Finds declaration of the property with name 'PropertyId' in the p...
ObjCImplementationDecl * getImplementation() const
known_extensions_range known_extensions() const
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCIvarRefExpr - A reference to an ObjC instance variable.
ObjCMethodDecl - Represents an instance or class method declaration.
ImplicitParamDecl * getSelfDecl() const
const ObjCPropertyDecl * findPropertyDecl(bool CheckOverrides=true) const
Returns the property associated with this method's selector.
bool isSynthesizedAccessorStub() const
Selector getSelector() const
QualType getReturnType() const
ObjCInterfaceDecl * getClassInterface()
Represents one property declaration in an Objective-C interface.
ObjCPropertyQueryKind getQueryKind() const
bool isReadOnly() const
isReadOnly - Return true iff the property has a setter.
ObjCIvarDecl * getPropertyIvarDecl() const
ObjCPropertyAttribute::Kind getPropertyAttributes() const
A single parameter index whose accessors require each use to make explicit the parameter index encodi...
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
bool isNull() const
Return true if this QualType doesn't point to a type yet.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
Represents a struct/union/class.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
static ReturnStmt * Create(const ASTContext &Ctx, SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
Create a return statement.
Encodes a location in the source.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isBooleanType() const
bool isRValueReferenceType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isReferenceType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
bool isObjCLifetimeType() const
Returns true if objects of this type have lifetime semantics under ARC.
const T * getAs() const
Member-template getAs<specific type>'.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
The JSON file list parser is used to communicate input to InstallAPI.
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
@ OK_Ordinary
An ordinary object is located at an address in memory.
CastKind
CastKind - The kind of operation required for a conversion.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_XValue
An x-value expression is a reference to an object with independent storage but which can be "moved",...
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
@ NOUR_None
This is an odr-use.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...