diff options
Diffstat (limited to 'clang/include')
-rw-r--r-- | clang/include/clang/AST/Expr.h | 146 | ||||
-rw-r--r-- | clang/include/clang/AST/RecursiveASTVisitor.h | 1 | ||||
-rw-r--r-- | clang/include/clang/Basic/Builtins.def | 13 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 9 | ||||
-rw-r--r-- | clang/include/clang/Basic/StmtNodes.td | 3 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 2 | ||||
-rw-r--r-- | clang/include/clang/Serialization/ASTBitCodes.h | 4 |
7 files changed, 176 insertions, 2 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 882124bfdd6..d7b6247b63c 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -4162,6 +4162,152 @@ public: // Iterators child_range children() { return child_range(&SrcExpr, &SrcExpr+1); } }; + +/// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, +/// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the +/// similarly-named C++0x instructions. All of these instructions take one +/// primary pointer and at least one memory order. +class AtomicExpr : public Expr { +public: + enum AtomicOp { Load, Store, CmpXchgStrong, CmpXchgWeak, Xchg, + Add, Sub, And, Or, Xor }; +private: + enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, END_EXPR }; + Stmt* SubExprs[END_EXPR]; + unsigned NumSubExprs; + SourceLocation BuiltinLoc, RParenLoc; + AtomicOp Op; + +public: + // Constructor for Load + AtomicExpr(SourceLocation BLoc, Expr *ptr, Expr *order, QualType t, + AtomicOp op, SourceLocation RP, + bool TypeDependent, bool ValueDependent) + : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary, + TypeDependent, ValueDependent, + ptr->isInstantiationDependent(), + ptr->containsUnexpandedParameterPack()), + BuiltinLoc(BLoc), RParenLoc(RP), Op(op) { + assert(op == Load && "single-argument atomic must be load"); + SubExprs[PTR] = ptr; + SubExprs[ORDER] = order; + NumSubExprs = 2; + } + + // Constructor for Store, Xchg, Add, Sub, And, Or, Xor + AtomicExpr(SourceLocation BLoc, Expr *ptr, Expr *val, Expr *order, + QualType t, AtomicOp op, SourceLocation RP, + bool TypeDependent, bool ValueDependent) + : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary, + TypeDependent, ValueDependent, + (ptr->isInstantiationDependent() || + val->isInstantiationDependent()), + (ptr->containsUnexpandedParameterPack() || + val->containsUnexpandedParameterPack())), + BuiltinLoc(BLoc), RParenLoc(RP), Op(op) { + assert(!isCmpXChg() && op != Load && + "two-argument atomic store or binop"); + SubExprs[PTR] = ptr; + SubExprs[ORDER] = order; + SubExprs[VAL1] = val; + NumSubExprs = 3; + } + + // Constructor for CmpXchgStrong, CmpXchgWeak + AtomicExpr(SourceLocation BLoc, Expr *ptr, Expr *val1, Expr *val2, + Expr *order, Expr *order_fail, QualType t, AtomicOp op, + SourceLocation RP, bool TypeDependent, bool ValueDependent) + : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary, + TypeDependent, ValueDependent, + (ptr->isInstantiationDependent() || + val1->isInstantiationDependent() || + val2->isInstantiationDependent()), + (ptr->containsUnexpandedParameterPack() || + val1->containsUnexpandedParameterPack() || + val2->containsUnexpandedParameterPack())), + BuiltinLoc(BLoc), RParenLoc(RP), Op(op) { + assert(isCmpXChg() && "three-argument atomic must be cmpxchg"); + SubExprs[PTR] = ptr; + SubExprs[ORDER] = order; + SubExprs[VAL1] = val1; + SubExprs[VAL2] = val2; + SubExprs[ORDER_FAIL] = order_fail; + NumSubExprs = 5; + } + + /// \brief Build an empty AtomicExpr. + explicit AtomicExpr(EmptyShell Empty) : Expr(AtomicExprClass, Empty) { } + + Expr *getPtr() const { + return cast<Expr>(SubExprs[PTR]); + } + void setPtr(Expr *E) { + SubExprs[PTR] = E; + } + Expr *getOrder() const { + return cast<Expr>(SubExprs[ORDER]); + } + void setOrder(Expr *E) { + SubExprs[ORDER] = E; + } + Expr *getVal1() const { + assert(NumSubExprs >= 3); + return cast<Expr>(SubExprs[VAL1]); + } + void setVal1(Expr *E) { + assert(NumSubExprs >= 3); + SubExprs[VAL1] = E; + } + Expr *getOrderFail() const { + assert(NumSubExprs == 5); + return cast<Expr>(SubExprs[ORDER_FAIL]); + } + void setOrderFail(Expr *E) { + assert(NumSubExprs == 5); + SubExprs[ORDER_FAIL] = E; + } + Expr *getVal2() const { + assert(NumSubExprs == 5); + return cast<Expr>(SubExprs[VAL2]); + } + void setVal2(Expr *E) { + assert(NumSubExprs == 5); + SubExprs[VAL2] = E; + } + + AtomicOp getOp() const { return Op; } + void setOp(AtomicOp op) { Op = op; } + unsigned getNumSubExprs() { return NumSubExprs; } + void setNumSubExprs(unsigned num) { NumSubExprs = num; } + + bool isVolatile() const { + return getPtr()->getType()->getPointeeType().isVolatileQualified(); + } + + bool isCmpXChg() const { + return getOp() == AtomicExpr::CmpXchgStrong || + getOp() == AtomicExpr::CmpXchgWeak; + } + + SourceLocation getBuiltinLoc() const { return BuiltinLoc; } + void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } + + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + SourceRange getSourceRange() const { + return SourceRange(BuiltinLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == AtomicExprClass; + } + static bool classof(const AtomicExpr *) { return true; } + + // Iterators + child_range children() { + return child_range(SubExprs, SubExprs+NumSubExprs); + } +}; } // end namespace clang #endif diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index a224bb0a40c..0ec09c9b09e 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1992,6 +1992,7 @@ DEF_TRAVERSE_STMT(SizeOfPackExpr, { }) DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { }) DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, { }) DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { }) +DEF_TRAVERSE_STMT(AtomicExpr, { }) // These literals (all of them) do not need any action. DEF_TRAVERSE_STMT(IntegerLiteral, { }) diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index 50b51c7a4f7..60bcde372ac 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -585,7 +585,18 @@ BUILTIN(__sync_swap_4, "iiD*i.", "n") BUILTIN(__sync_swap_8, "LLiLLiD*LLi.", "n") BUILTIN(__sync_swap_16, "LLLiLLLiD*LLLi.", "n") - +BUILTIN(__atomic_load, "v.", "t") +BUILTIN(__atomic_store, "v.", "t") +BUILTIN(__atomic_exchange, "v.", "t") +BUILTIN(__atomic_compare_exchange_strong, "v.", "t") +BUILTIN(__atomic_compare_exchange_weak, "v.", "t") +BUILTIN(__atomic_fetch_add, "v.", "t") +BUILTIN(__atomic_fetch_sub, "v.", "t") +BUILTIN(__atomic_fetch_and, "v.", "t") +BUILTIN(__atomic_fetch_or, "v.", "t") +BUILTIN(__atomic_fetch_xor, "v.", "t") +BUILTIN(__atomic_thread_fence, "vi", "t") +BUILTIN(__atomic_signal_fence, "vi", "t") // Non-overloaded atomic builtins. BUILTIN(__sync_synchronize, "v.", "n") diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a1be656fac3..240401b3939 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4012,6 +4012,15 @@ def err_atomic_builtin_must_be_pointer_intptr : Error< def err_atomic_builtin_pointer_size : Error< "first argument to atomic builtin must be a pointer to 1,2,4,8 or 16 byte " "type (%0 invalid)">; +def err_atomic_op_needs_atomic : Error< + "first argument to atomic operation must be a pointer to _Atomic " + "type (%0 invalid)">; +def err_atomic_op_needs_atomic_int_or_ptr : Error< + "first argument to atomic operation must be a pointer to atomic " + "integer or pointer (%0 invalid)">; +def err_atomic_op_logical_needs_atomic_int : Error< + "first argument to logical atomic operation must be a pointer to atomic " + "integer (%0 invalid)">; def err_deleted_function_use : Error<"attempt to use a deleted function">; diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 73996e43d5d..7b3d7762c24 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -78,6 +78,9 @@ def ParenListExpr : DStmt<Expr>; def VAArgExpr : DStmt<Expr>; def GenericSelectionExpr : DStmt<Expr>; +// Atomic expressions +def AtomicExpr : DStmt<Expr>; + // GNU Extensions. def AddrLabelExpr : DStmt<Expr>; def StmtExpr : DStmt<Expr>; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 39c98997611..fec14c58260 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6084,6 +6084,8 @@ private: bool SemaBuiltinObjectSize(CallExpr *TheCall); bool SemaBuiltinLongjmp(CallExpr *TheCall); ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult); + ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult, + AtomicExpr::AtomicOp Op); bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, llvm::APSInt &Result); diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 9a8eba24274..1efd7542177 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -973,7 +973,9 @@ namespace clang { EXPR_BLOCK_DECL_REF, /// \brief A GenericSelectionExpr record. EXPR_GENERIC_SELECTION, - + /// \brief An AtomicExpr record. + EXPR_ATOMIC, + // Objective-C /// \brief An ObjCStringLiteral record. |