From: Eli Friedman Date: Fri, 14 Oct 2011 22:48:56 +0000 (+0000) Subject: Add template instantiation support for AtomicExpr. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dfa64ba45922e1c28e36341bdf34785fea74659b;p=clang Add template instantiation support for AtomicExpr. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142012 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index d7b6247b63..1242f4e6c7 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -4179,61 +4179,8 @@ private: 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; - } + AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr, QualType t, + AtomicOp op, SourceLocation RP); /// \brief Build an empty AtomicExpr. explicit AtomicExpr(EmptyShell Empty) : Expr(AtomicExprClass, Empty) { } @@ -4280,6 +4227,8 @@ public: unsigned getNumSubExprs() { return NumSubExprs; } void setNumSubExprs(unsigned num) { NumSubExprs = num; } + Expr **getSubExprs() { return reinterpret_cast(SubExprs); } + bool isVolatile() const { return getPtr()->getType()->getPointeeType().isVolatileQualified(); } diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 8a3a74c2bd..2a6fd6bc96 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -146,6 +146,7 @@ protected: friend class CXXUnresolvedConstructExpr; // ctor friend class CXXDependentScopeMemberExpr; // ctor friend class OverloadExpr; // ctor + friend class AtomicExpr; // ctor unsigned : NumStmtBits; unsigned ValueKind : 2; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 49a255a369..b0bcfe09f6 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -3315,3 +3315,24 @@ BlockDeclRefExpr::BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK, ExprBits.ValueDependent = ValueDependent; ExprBits.InstantiationDependent = InstantiationDependent; } + + +AtomicExpr::AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr, + QualType t, AtomicOp op, SourceLocation RP) + : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary, + false, false, false, false), + NumSubExprs(nexpr), BuiltinLoc(BLoc), RParenLoc(RP), Op(op) +{ + for (unsigned i = 0; i < nexpr; i++) { + if (args[i]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (args[i]->isValueDependent()) + ExprBits.ValueDependent = true; + if (args[i]->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (args[i]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + SubExprs[i] = args[i]; + } +} diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 74c69a3ce3..310138354b 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -475,7 +475,6 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op) { CallExpr *TheCall = cast(TheCallResult.get()); DeclRefExpr *DRE =cast(TheCall->getCallee()->IgnoreParenCasts()); - Expr *Ptr, *Order, *Val1, *Val2, *OrderFail; // All these operations take one of the following four forms: // T __atomic_load(_Atomic(T)*, int) (loads) @@ -508,7 +507,7 @@ Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op) // Inspect the first argument of the atomic operation. This should always be // a pointer to an _Atomic type. - Ptr = TheCall->getArg(0); + Expr *Ptr = TheCall->getArg(0); Ptr = DefaultFunctionArrayLvalueConversion(Ptr).get(); const PointerType *pointerType = Ptr->getType()->getAs(); if (!pointerType) { @@ -591,30 +590,24 @@ Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op) TheCall->setArg(i, Arg.get()); } + SmallVector SubExprs; + SubExprs.push_back(Ptr); if (Op == AtomicExpr::Load) { - Order = TheCall->getArg(1); - return Owned(new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(), - Ptr, Order, ResultType, Op, - TheCall->getRParenLoc(), false, - false)); + SubExprs.push_back(TheCall->getArg(1)); // Order } else if (Op != AtomicExpr::CmpXchgWeak && Op != AtomicExpr::CmpXchgStrong) { - Val1 = TheCall->getArg(1); - Order = TheCall->getArg(2); - return Owned(new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(), - Ptr, Val1, Order, ResultType, Op, - TheCall->getRParenLoc(), false, - false)); + SubExprs.push_back(TheCall->getArg(2)); // Order + SubExprs.push_back(TheCall->getArg(1)); // Val1 } else { - Val1 = TheCall->getArg(1); - Val2 = TheCall->getArg(2); - Order = TheCall->getArg(3); - OrderFail = TheCall->getArg(4); - return Owned(new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(), - Ptr, Val1, Val2, Order, OrderFail, - ResultType, Op, - TheCall->getRParenLoc(), false, - false)); + SubExprs.push_back(TheCall->getArg(3)); // Order + SubExprs.push_back(TheCall->getArg(1)); // Val1 + SubExprs.push_back(TheCall->getArg(2)); // Val2 + SubExprs.push_back(TheCall->getArg(4)); // OrderFail } + + return Owned(new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(), + SubExprs.data(), SubExprs.size(), + ResultType, Op, + TheCall->getRParenLoc())); } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 4a2ad18e71..bb49eee2f3 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2385,7 +2385,26 @@ public: llvm::Optional NumExpansions) { return getSema().CheckPackExpansion(Pattern, EllipsisLoc, NumExpansions); } - + + /// \brief Build a new atomic operation expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildAtomicExpr(SourceLocation BuiltinLoc, + MultiExprArg SubExprs, + QualType RetTy, + AtomicExpr::AtomicOp Op, + SourceLocation RParenLoc) { + // Just create the expression; there is not any interesting semantic + // analysis here because we can't actually build an AtomicExpr until + // we are sure it is semantically sound. + unsigned NumSubExprs = SubExprs.size(); + Expr **Subs = (Expr **)SubExprs.release(); + return new (SemaRef.Context) AtomicExpr(BuiltinLoc, Subs, + NumSubExprs, RetTy, Op, + RParenLoc); + } + private: TypeLoc TransformTypeInObjectScope(TypeLoc TL, QualType ObjectType, @@ -8103,8 +8122,20 @@ TreeTransform::TransformAsTypeExpr(AsTypeExpr *E) { template ExprResult TreeTransform::TransformAtomicExpr(AtomicExpr *E) { - assert(false && "Cannot transform atomic expressions yet"); - return SemaRef.Owned(E); + QualType RetTy = getDerived().TransformType(E->getType()); + bool ArgumentChanged = false; + ASTOwningVector SubExprs(SemaRef); + SubExprs.reserve(E->getNumSubExprs()); + if (getDerived().TransformExprs(E->getSubExprs(), E->getNumSubExprs(), false, + SubExprs, &ArgumentChanged)) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + !ArgumentChanged) + return SemaRef.Owned(E); + + return getDerived().RebuildAtomicExpr(E->getBuiltinLoc(), move_arg(SubExprs), + RetTy, E->getOp(), E->getRParenLoc()); } //===----------------------------------------------------------------------===//