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;
224 nullptr, MemberDecl->
getType(), ValueKind,
240 return cast<ValueDecl>(FoundDecl);
259 SubExpr = M.makeImplicitCast(
264 SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay);
270 llvm_unreachable(
"Unexpected state");
281 assert(CallbackDecl !=
nullptr);
284 assert(callOperatorDecl !=
nullptr);
290 const_cast<FunctionDecl *>(callOperatorDecl),
293 callOperatorDecl->getType(),
320 LLVM_DEBUG(llvm::dbgs() <<
"Generating body for call_once\n");
332 llvm::dbgs() <<
"libcxx03 std::call_once implementation, skipping.\n";
336 llvm::dbgs() <<
"unknown std::call_once implementation, skipping.\n";
347 if (!FlagRecordDecl) {
348 LLVM_DEBUG(llvm::dbgs() <<
"Flag field is not a record: " 349 <<
"unknown std::call_once implementation, " 350 <<
"ignoring the call.\n");
356 ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl,
"__state_");
360 if (!FlagFieldDecl) {
361 FlagFieldDecl = M.findMemberField(FlagRecordDecl,
"_M_once");
364 if (!FlagFieldDecl) {
365 LLVM_DEBUG(llvm::dbgs() <<
"No field _M_once or __state_ found on " 366 <<
"std::once_flag struct: unknown std::call_once " 367 <<
"implementation, ignoring the call.");
371 bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->
isLambda();
372 if (CallbackRecordDecl && !isLambdaCall) {
373 LLVM_DEBUG(llvm::dbgs()
374 <<
"Not supported: synthesizing body for functors when " 375 <<
"body farming std::call_once, ignoring the call.");
385 M.makeDeclRefExpr(Callback,
391 CallbackFunctionType =
397 if (!CallbackFunctionType)
402 LLVM_DEBUG(llvm::dbgs() <<
"Types of params of the callback do not match " 403 <<
"params passed to std::call_once, " 404 <<
"ignoring the call\n");
418 LLVM_DEBUG(llvm::dbgs() <<
"Types of params of the callback do not match " 419 <<
"params passed to std::call_once, " 420 <<
"ignoring the call\n");
423 Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
426 ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
428 CallArgs.push_back(ParamExpr);
435 CallbackRecordDecl, CallArgs);
443 M.makeDeclRefExpr(Flag,
447 MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl);
454 M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
455 CK_IntegralToBoolean),
464 Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.
IntTy), DerefType),
473 M.makeCompound({CallbackCall, FlagAssignment}));
515 M.makeLvalueToRvalue(Block),
530 M.makeLvalueToRvalue(
531 M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
533 M.makeIntegralCast(DoneValue, PredicateTy),
537 Stmt *Stmts[] = { B, CE };
542 M.makeLvalueToRvalue(
544 M.makeLvalueToRvalue(
545 M.makeDeclRefExpr(Predicate),
550 Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE);
616 assert(OldValueTy == NewValueTy);
629 M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
630 M.makeLvalueToRvalue(
632 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
642 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
644 M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
647 Expr *BoolVal = M.makeObjCBool(
true);
648 Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
649 : M.makeIntegralCast(BoolVal, ResultTy);
650 Stmts[1] = M.makeReturn(RetVal);
654 BoolVal = M.makeObjCBool(
false);
655 RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
656 : M.makeIntegralCast(BoolVal, ResultTy);
657 Stmt *Else = M.makeReturn(RetVal);
671 return Val.getValue();
684 if (Name.startswith(
"OSAtomicCompareAndSwap") ||
685 Name.startswith(
"objc_atomicCompareAndSwap")) {
690 FF = llvm::StringSwitch<FunctionFarmer>(Name)
696 if (FF) { Val = FF(
C, D); }
697 else if (Injector) { Val = Injector->getBody(D); }
698 return Val.getValue();
716 auto *Container = cast<ObjCContainerDecl>(Prop->
getDeclContext());
718 if (
auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
719 PrimaryInterface = InterfaceDecl;
720 }
else if (
auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
721 PrimaryInterface = CategoryDecl->getClassInterface();
722 }
else if (
auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
723 PrimaryInterface = ImplDecl->getClassInterface();
733 if (ShadowingProp && ShadowingProp != Prop) {
734 IVar = ShadowingProp->getPropertyIvarDecl();
760 if (I->getPropertyDecl() != Prop)
763 if (I->getGetterCXXConstructor()) {
765 return M.makeReturn(I->getGetterCXXConstructor());
790 M.makeLvalueToRvalue(
791 M.makeDeclRefExpr(selfVar),
796 loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->
getType());
798 return M.makeReturn(loadedIVar);
810 return Val.getValue();
831 return Val.getValue();
A call to an overloaded operator written using operator syntax.
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.
IfStmt - This represents an if/then/else.
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 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 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...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Expr - 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.
DeclarationName - 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.