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);
104 bool IsArrow =
false,
128 const_cast<Expr*
>(RHS),
130 C.getLogicalOperationType(),
141 bool RefersToEnclosingVariableOrCapture) {
151 return new (
C)
UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty,
157 return makeImplicitCast(Arg, Ty, CK_LValueToRValue);
161 ASTMaker::makeLvalueToRvalue(
const VarDecl *Arg,
162 bool RefersToEnclosingVariableOrCapture) {
164 return makeLvalueToRvalue(makeDeclRefExpr(Arg,
165 RefersToEnclosingVariableOrCapture),
173 const_cast<Expr *>(Arg),
180 return const_cast<Expr*>(Arg);
183 const_cast<Expr*>(Arg),
nullptr,
VK_RValue);
188 const_cast<Expr*>(Arg),
nullptr,
VK_RValue);
192 QualType Ty =
C.getBOOLDecl() ?
C.getBOOLType() :
C.ObjCBuiltinBoolTy;
223 nullptr, MemberDecl->
getType(), ValueKind,
239 return cast<ValueDecl>(FoundDecl);
258 SubExpr = M.makeImplicitCast(
263 SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay);
269 llvm_unreachable(
"Unexpected state");
280 assert(CallbackDecl !=
nullptr);
283 assert(callOperatorDecl !=
nullptr);
289 const_cast<FunctionDecl *>(callOperatorDecl),
292 callOperatorDecl->getType(),
296 C, OO_Call, callOperatorDeclRef,
319 LLVM_DEBUG(llvm::dbgs() <<
"Generating body for call_once\n");
331 llvm::dbgs() <<
"libcxx03 std::call_once implementation, skipping.\n";
335 llvm::dbgs() <<
"unknown std::call_once implementation, skipping.\n";
346 if (!FlagRecordDecl) {
347 LLVM_DEBUG(llvm::dbgs() <<
"Flag field is not a record: " 348 <<
"unknown std::call_once implementation, " 349 <<
"ignoring the call.\n");
355 ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl,
"__state_");
359 if (!FlagFieldDecl) {
360 FlagFieldDecl = M.findMemberField(FlagRecordDecl,
"_M_once");
363 if (!FlagFieldDecl) {
364 LLVM_DEBUG(llvm::dbgs() <<
"No field _M_once or __state_ found on " 365 <<
"std::once_flag struct: unknown std::call_once " 366 <<
"implementation, ignoring the call.");
370 bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->
isLambda();
371 if (CallbackRecordDecl && !isLambdaCall) {
372 LLVM_DEBUG(llvm::dbgs()
373 <<
"Not supported: synthesizing body for functors when " 374 <<
"body farming std::call_once, ignoring the call.");
384 M.makeDeclRefExpr(Callback,
390 CallbackFunctionType =
396 if (!CallbackFunctionType)
401 LLVM_DEBUG(llvm::dbgs() <<
"Types of params of the callback do not match " 402 <<
"params passed to std::call_once, " 403 <<
"ignoring the call\n");
417 LLVM_DEBUG(llvm::dbgs() <<
"Types of params of the callback do not match " 418 <<
"params passed to std::call_once, " 419 <<
"ignoring the call\n");
422 Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
425 ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
427 CallArgs.push_back(ParamExpr);
434 CallbackRecordDecl, CallArgs);
442 M.makeDeclRefExpr(Flag,
446 MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl);
453 M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
454 CK_IntegralToBoolean),
463 Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.
IntTy), DerefType),
472 M.makeCompound({CallbackCall, FlagAssignment}));
514 M.makeLvalueToRvalue(Block),
529 M.makeLvalueToRvalue(
530 M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
532 M.makeIntegralCast(DoneValue, PredicateTy),
536 Stmt *Stmts[] = { B, CE };
541 M.makeLvalueToRvalue(
543 M.makeLvalueToRvalue(
544 M.makeDeclRefExpr(Predicate),
549 Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE);
615 assert(OldValueTy == NewValueTy);
628 M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
629 M.makeLvalueToRvalue(
631 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
641 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
643 M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
646 Expr *BoolVal = M.makeObjCBool(
true);
647 Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
648 : M.makeIntegralCast(BoolVal, ResultTy);
649 Stmts[1] = M.makeReturn(RetVal);
653 BoolVal = M.makeObjCBool(
false);
654 RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
655 : M.makeIntegralCast(BoolVal, ResultTy);
656 Stmt *Else = M.makeReturn(RetVal);
662 nullptr, Comparison, Body,
673 return Val.getValue();
686 if (Name.startswith(
"OSAtomicCompareAndSwap") ||
687 Name.startswith(
"objc_atomicCompareAndSwap")) {
692 FF = llvm::StringSwitch<FunctionFarmer>(Name)
698 if (FF) { Val = FF(
C, D); }
699 else if (Injector) { Val = Injector->getBody(D); }
700 return Val.getValue();
718 auto *Container = cast<ObjCContainerDecl>(Prop->
getDeclContext());
720 if (
auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
721 PrimaryInterface = InterfaceDecl;
722 }
else if (
auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
723 PrimaryInterface = CategoryDecl->getClassInterface();
724 }
else if (
auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
725 PrimaryInterface = ImplDecl->getClassInterface();
735 if (ShadowingProp && ShadowingProp != Prop) {
736 IVar = ShadowingProp->getPropertyIvarDecl();
762 if (I->getPropertyDecl() != Prop)
765 if (I->getGetterCXXConstructor()) {
767 return M.makeReturn(I->getGetterCXXConstructor());
792 M.makeLvalueToRvalue(
793 M.makeDeclRefExpr(selfVar),
798 loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->
getType());
800 return M.makeReturn(loadedIVar);
812 return Val.getValue();
833 return Val.getValue();
Defines the clang::ASTContext interface.
ObjCPropertyQueryKind getQueryKind() const
Represents a function declaration or definition.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
unsigned param_size() const
Stmt - This represents one statement.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Decl - This represents one declaration (or definition), e.g.
static Stmt * create_call_once(ASTContext &C, const FunctionDecl *D)
Create a fake body for std::call_once.
static CallExpr * create_call_once_funcptr_call(ASTContext &C, ASTMaker M, const ParmVarDecl *Callback, ArrayRef< Expr *> CallArgs)
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
The base class of the type hierarchy.
Floating point control options.
size_t param_size() const
static CXXOperatorCallExpr * Create(const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn, ArrayRef< Expr *> Args, QualType Ty, ExprValueKind VK, SourceLocation OperatorLoc, FPOptions FPFeatures, ADLCallKind UsesADL=NotADL)
static bool isDispatchBlock(QualType Ty)
Represents a variable declaration or definition.
QualType getReturnType() const
unsigned getNumParams() const
const T * getAs() const
Member-template getAs<specific type>'.
ObjCMethodDecl - Represents an instance or class method declaration.
Represents a parameter to a function.
Defines the clang::Expr interface and subclasses for C++ expressions.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Represents a struct/union/class.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
One of these records is kept for each identifier that is lexed.
QualType getPointeeType() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
A C++ nested-name-specifier augmented with source location information.
The results of name lookup within a DeclContext.
bool isObjCLifetimeType() const
Returns true if objects of this type have lifetime semantics under ARC.
Defines the clang::CodeInjector interface which is responsible for injecting AST of function definiti...
bool isReferenceType() const
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)
An r-value expression (a pr-value in the C++11 taxonomy) produces a temporary value.
static IfStmt * Create(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond, Stmt *Then, SourceLocation EL=SourceLocation(), Stmt *Else=nullptr)
Create an IfStmt.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
PropertyAttributeKind getPropertyAttributes() const
A builtin binary operation expression such as "x + y" or "x <= y".
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt *> Stmts, SourceLocation LB, SourceLocation RB)
bool isRValueReferenceType() const
bool isReadOnly() const
isReadOnly - Return true iff the property has a setter.
bool isLambda() const
Determine whether this class describes a lambda function object.
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'.
An ordinary object is located at an address in memory.
Represents an ObjC class declaration.
Stmt *(* FunctionFarmer)(ASTContext &C, const FunctionDecl *D)
ObjCMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
CompoundStmt - This represents a group of statements like { stmt stmt }.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Represents a prototype with parameter type info, e.g.
CastKind
CastKind - The kind of operation required for a conversion.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat)
static const ObjCIvarDecl * findBackingIvar(const ObjCPropertyDecl *Prop)
A single parameter index whose accessors require each use to make explicit the parameter index encodi...
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr *> Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
This represents one expression.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
Defines an enumeration for C++ overloaded operators.
DeclContext * getDeclContext()
ObjCPropertyDecl * FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId, ObjCPropertyQueryKind QueryKind) const
FindPropertyVisibleInPrimaryClass - Finds declaration of the property with name 'PropertyId' in the p...
bool isFunctionOrMethod() const
propimpl_range property_impls() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
static Stmt * create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
static Stmt * createObjCPropertyGetter(ASTContext &Ctx, const ObjCPropertyDecl *Prop)
bool isNull() const
Return true if this QualType doesn't point to a type yet.
ImplicitParamDecl * getSelfDecl() const
bool isComparisonOp() const
QualType getCanonicalType() const
Encodes a location in the source.
QualType getReturnType() const
static Stmt * create_dispatch_sync(ASTContext &C, const FunctionDecl *D)
Create a fake body for dispatch_sync.
static CallExpr * create_call_once_lambda_call(ASTContext &C, ASTMaker M, const ParmVarDecl *Callback, CXXRecordDecl *CallbackDecl, ArrayRef< Expr *> CallArgs)
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
bool isStdNamespace() const
const ParmVarDecl * getParamDecl(unsigned i) const
Represents one property declaration in an Objective-C interface.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language...
ObjCImplementationDecl * getImplementation() const
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
static MemberExpr * Create(const ASTContext &C, Expr *base, bool isarrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *memberdecl, DeclAccessPair founddecl, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *targs, QualType ty, ExprValueKind VK, ExprObjectKind OK)
A POD class for pairing a NamedDecl* with an access specifier.
static Stmt * create_dispatch_once(ASTContext &C, const FunctionDecl *D)
Create a fake body for dispatch_once.
Dataflow Directional Tag Classes.
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
static ReturnStmt * Create(const ASTContext &Ctx, SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
Create a return statement.
The name of a declaration.
bool isBooleanType() const
Stmt * getBody(const FunctionDecl *D)
Factory method for creating bodies for ordinary functions.
const ObjCInterfaceDecl * getContainingInterface() const
Return the class interface that this ivar is logically contained in; this is either the interface whe...
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isFunctionType() const
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat]...
ObjCIvarRefExpr - A reference to an ObjC instance variable.
bool isLValueReferenceType() const
const ObjCPropertyDecl * findPropertyDecl(bool CheckOverrides=true) const
Returns the property associated with this method's selector.
QualType getParamType(unsigned i) const
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Represents a C++ struct/union/class.
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCIvarDecl * getPropertyIvarDecl() const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
ObjCBoolLiteralExpr - Objective-C Boolean Literal.
A reference to a declared variable, function, enum, etc.
bool isPointerType() const
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
An l-value expression is a reference to an object with independent storage.
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
ObjCMethodDecl * getGetterMethodDecl() const
This represents a decl that may have a name.
bool isPropertyAccessor() const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.