24 #include "llvm/ADT/StringSwitch.h" 25 #include "llvm/Support/Debug.h" 27 #define DEBUG_TYPE "body-farm" 29 using namespace clang;
65 bool RefersToEnclosingVariableOrCapture =
false);
83 bool RefersToEnclosingVariableOrCapture =
false);
103 bool IsArrow =
false,
127 const_cast<Expr*
>(RHS),
129 C.getLogicalOperationType(),
140 bool RefersToEnclosingVariableOrCapture) {
150 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;
222 nullptr, MemberDecl->
getType(), ValueKind,
238 return cast<ValueDecl>(FoundDecl);
257 SubExpr = M.makeImplicitCast(
262 SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay);
268 llvm_unreachable(
"Unexpected state");
279 assert(CallbackDecl !=
nullptr);
282 assert(callOperatorDecl !=
nullptr);
288 const_cast<FunctionDecl *>(callOperatorDecl),
291 callOperatorDecl->getType(),
295 C, OO_Call, callOperatorDeclRef,
318 LLVM_DEBUG(llvm::dbgs() <<
"Generating body for call_once\n");
330 llvm::dbgs() <<
"libcxx03 std::call_once implementation, skipping.\n";
334 llvm::dbgs() <<
"unknown std::call_once implementation, skipping.\n";
345 if (!FlagRecordDecl) {
346 LLVM_DEBUG(llvm::dbgs() <<
"Flag field is not a record: " 347 <<
"unknown std::call_once implementation, " 348 <<
"ignoring the call.\n");
354 ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl,
"__state_");
358 if (!FlagFieldDecl) {
359 FlagFieldDecl = M.findMemberField(FlagRecordDecl,
"_M_once");
362 if (!FlagFieldDecl) {
363 LLVM_DEBUG(llvm::dbgs() <<
"No field _M_once or __state_ found on " 364 <<
"std::once_flag struct: unknown std::call_once " 365 <<
"implementation, ignoring the call.");
369 bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->
isLambda();
370 if (CallbackRecordDecl && !isLambdaCall) {
371 LLVM_DEBUG(llvm::dbgs()
372 <<
"Not supported: synthesizing body for functors when " 373 <<
"body farming std::call_once, ignoring the call.");
383 M.makeDeclRefExpr(Callback,
389 CallbackFunctionType =
395 if (!CallbackFunctionType)
400 LLVM_DEBUG(llvm::dbgs() <<
"Types of params of the callback do not match " 401 <<
"params passed to std::call_once, " 402 <<
"ignoring the call\n");
416 LLVM_DEBUG(llvm::dbgs() <<
"Types of params of the callback do not match " 417 <<
"params passed to std::call_once, " 418 <<
"ignoring the call\n");
421 Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
424 ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
426 CallArgs.push_back(ParamExpr);
433 CallbackRecordDecl, CallArgs);
441 M.makeDeclRefExpr(Flag,
445 MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl);
452 M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
453 CK_IntegralToBoolean),
462 Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.
IntTy), DerefType),
471 M.makeCompound({CallbackCall, FlagAssignment}));
513 M.makeLvalueToRvalue(Block),
528 M.makeLvalueToRvalue(
529 M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
531 M.makeIntegralCast(DoneValue, PredicateTy),
535 Stmt *Stmts[] = { B, CE };
540 M.makeLvalueToRvalue(
542 M.makeLvalueToRvalue(
543 M.makeDeclRefExpr(Predicate),
548 Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE);
614 assert(OldValueTy == NewValueTy);
627 M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
628 M.makeLvalueToRvalue(
630 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
640 M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
642 M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
645 Expr *BoolVal = M.makeObjCBool(
true);
646 Expr *RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
647 : M.makeIntegralCast(BoolVal, ResultTy);
648 Stmts[1] = M.makeReturn(RetVal);
652 BoolVal = M.makeObjCBool(
false);
653 RetVal = isBoolean ? M.makeIntegralCastToBoolean(BoolVal)
654 : M.makeIntegralCast(BoolVal, ResultTy);
655 Stmt *Else = M.makeReturn(RetVal);
661 nullptr, Comparison, Body,
670 return Val.getValue();
683 if (Name.startswith(
"OSAtomicCompareAndSwap") ||
684 Name.startswith(
"objc_atomicCompareAndSwap")) {
689 FF = llvm::StringSwitch<FunctionFarmer>(Name)
695 if (FF) { Val = FF(
C, D); }
696 else if (Injector) { Val = Injector->getBody(D); }
697 return Val.getValue();
715 auto *Container = cast<ObjCContainerDecl>(Prop->
getDeclContext());
717 if (
auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
718 PrimaryInterface = InterfaceDecl;
719 }
else if (
auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
720 PrimaryInterface = CategoryDecl->getClassInterface();
721 }
else if (
auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
722 PrimaryInterface = ImplDecl->getClassInterface();
732 if (ShadowingProp && ShadowingProp != Prop) {
733 IVar = ShadowingProp->getPropertyIvarDecl();
759 if (I->getPropertyDecl() != Prop)
762 if (I->getGetterCXXConstructor()) {
764 return M.makeReturn(I->getGetterCXXConstructor());
789 M.makeLvalueToRvalue(
790 M.makeDeclRefExpr(selfVar),
795 loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->
getType());
797 return M.makeReturn(loadedIVar);
814 return Val.getValue();
835 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
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.
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)
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.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
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.
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).
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)
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.
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.