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,
156 return makeImplicitCast(Arg, Ty, CK_LValueToRValue);
160 ASTMaker::makeLvalueToRvalue(
const VarDecl *Arg,
161 bool RefersToEnclosingVariableOrCapture) {
163 return makeLvalueToRvalue(makeDeclRefExpr(Arg,
164 RefersToEnclosingVariableOrCapture),
172 const_cast<Expr *>(Arg),
179 return const_cast<Expr*>(Arg);
182 const_cast<Expr*>(Arg),
nullptr,
VK_RValue);
187 const_cast<Expr*>(Arg),
nullptr,
VK_RValue);
191 QualType Ty =
C.getBOOLDecl() ?
C.getBOOLType() :
C.ObjCBuiltinBoolTy;
223 nullptr, MemberDecl->
getType(), ValueKind,
239 return cast<ValueDecl>(FoundDecl);
258 CK = CK_LValueToRValue;
261 CK = CK_FunctionToPointerDecay;
277 assert(CallbackDecl !=
nullptr);
280 assert(callOperatorDecl !=
nullptr);
286 const_cast<FunctionDecl *>(callOperatorDecl),
289 callOperatorDecl->getType(),
316 DEBUG(llvm::dbgs() <<
"Generating body for call_once\n");
328 llvm::dbgs() <<
"libcxx03 std::call_once implementation, skipping.\n";
332 llvm::dbgs() <<
"unknown std::call_once implementation, skipping.\n";
341 auto *FlagRecordDecl = dyn_cast_or_null<RecordDecl>(FlagType->
getAsTagDecl());
343 if (!FlagRecordDecl) {
344 DEBUG(llvm::dbgs() <<
"Flag field is not a record: " 345 <<
"unknown std::call_once implementation, " 346 <<
"ignoring the call.\n");
352 ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl,
"__state_");
356 if (!FlagFieldDecl) {
357 FlagFieldDecl = M.findMemberField(FlagRecordDecl,
"_M_once");
360 if (!FlagFieldDecl) {
361 DEBUG(llvm::dbgs() <<
"No field _M_once or __state_ found on " 362 <<
"std::once_flag struct: unknown std::call_once " 363 <<
"implementation, ignoring the call.");
367 bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->
isLambda();
368 if (CallbackRecordDecl && !isLambdaCall) {
369 DEBUG(llvm::dbgs() <<
"Not supported: synthesizing body for functors when " 370 <<
"body farming std::call_once, ignoring the call.");
380 M.makeDeclRefExpr(Callback,
386 CallbackFunctionType =
392 if (!CallbackFunctionType)
397 DEBUG(llvm::dbgs() <<
"Types of params of the callback do not match " 398 <<
"params passed to std::call_once, " 399 <<
"ignoring the call\n");
406 for (
unsigned int ParamIdx = 2; ParamIdx < D->
getNumParams(); ParamIdx++) {
408 Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
411 ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
413 CallArgs.push_back(ParamExpr);
420 CallbackRecordDecl, CallArgs);
428 M.makeDeclRefExpr(Flag,
432 MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl);
439 M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
440 CK_IntegralToBoolean),
448 Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.
IntTy), DerefType),
457 M.makeCompound({CallbackCall, FlagAssignment}));
499 M.makeLvalueToRvalue(Block),
513 M.makeLvalueToRvalue(
514 M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
516 M.makeIntegralCast(DoneValue, PredicateTy),
520 Stmt *Stmts[] = { B, CE };
525 M.makeLvalueToRvalue(
527 M.makeLvalueToRvalue(
528 M.makeDeclRefExpr(Predicate),
533 Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE);
599 assert(OldValueTy == NewValueTy);
612 M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
613 M.makeLvalueToRvalue(
615 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
625 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
627 M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
630 Expr *BoolVal = M.makeObjCBool(
true);
631 Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
632 : M.makeIntegralCast(BoolVal, ResultTy);
633 Stmts[1] = M.makeReturn(RetVal);
637 BoolVal = M.makeObjCBool(
false);
638 RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
639 : M.makeIntegralCast(BoolVal, ResultTy);
640 Stmt *Else = M.makeReturn(RetVal);
654 return Val.getValue();
667 if (Name.startswith(
"OSAtomicCompareAndSwap") ||
668 Name.startswith(
"objc_atomicCompareAndSwap")) {
673 FF = llvm::StringSwitch<FunctionFarmer>(Name)
679 if (FF) { Val = FF(
C, D); }
680 else if (Injector) { Val = Injector->getBody(D); }
681 return Val.getValue();
699 auto *Container = cast<ObjCContainerDecl>(Prop->
getDeclContext());
701 if (
auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
702 PrimaryInterface = InterfaceDecl;
703 }
else if (
auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
704 PrimaryInterface = CategoryDecl->getClassInterface();
705 }
else if (
auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
706 PrimaryInterface = ImplDecl->getClassInterface();
716 if (ShadowingProp && ShadowingProp != Prop) {
717 IVar = ShadowingProp->getPropertyIvarDecl();
743 if (I->getPropertyDecl() != Prop)
746 if (I->getGetterCXXConstructor()) {
748 return M.makeReturn(I->getGetterCXXConstructor());
773 M.makeLvalueToRvalue(
774 M.makeDeclRefExpr(selfVar),
779 loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->
getType());
781 return M.makeReturn(loadedIVar);
793 return Val.getValue();
814 return Val.getValue();
A call to an overloaded operator written using operator syntax.
Defines the clang::ASTContext interface.
ObjCPropertyQueryKind getQueryKind() const
An instance of this class is created to represent 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)
VarDecl - An instance of this class is created to represent 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.
ParmVarDecl - Represents a parameter to a function.
Defines the clang::Expr interface and subclasses for C++ expressions.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
RecordDecl - Represents a struct/union/class.
DeclarationName getDeclName() const
getDeclName - 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.
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)
ValueDecl - Represent the declaration of a variable (in which case it is an lvalue) a function (in wh...
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
TagDecl * getAsTagDecl() const
Retrieves the TagDecl that this type refers to, either because the type is a TagType or because it is...
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
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).
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
getName - 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.
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
NamedDecl - This represents a decl with a name.
bool isPropertyAccessor() const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.