summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Liao <michael.hliao@gmail.com>2019-09-23 18:48:06 +0000
committerMichael Liao <michael.hliao@gmail.com>2019-09-23 18:48:06 +0000
commit566b3164c51e618522579637cf65174ba357b852 (patch)
treef851742e0eeef47b7b2fdc75c99ae585f70b1e9f
parent47e1ce4abea11784adab84af92b4a1f0e1426cc9 (diff)
downloadbcm5719-llvm-566b3164c51e618522579637cf65174ba357b852.tar.gz
bcm5719-llvm-566b3164c51e618522579637cf65174ba357b852.zip
[Sema] Fix the atomic expr rebuilding order.
Summary: - Rearrange the atomic expr order to the API order when rebuilding atomic expr during template instantiation. Reviewers: erichkeane Subscribers: jfb, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D67924 llvm-svn: 372640
-rw-r--r--clang/include/clang/Sema/Sema.h9
-rw-r--r--clang/lib/Sema/SemaChecking.cpp90
-rw-r--r--clang/lib/Sema/TreeTransform.h6
-rw-r--r--clang/test/AST/atomic-expr.cpp43
4 files changed, 116 insertions, 32 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9c2226f83c2..da103ba75a8 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4637,9 +4637,12 @@ public:
MultiExprArg ArgExprs, SourceLocation RParenLoc,
Expr *ExecConfig = nullptr,
bool IsExecConfig = false);
- ExprResult BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
- SourceLocation RParenLoc, MultiExprArg Args,
- AtomicExpr::AtomicOp Op);
+ enum class AtomicArgumentOrder { API, AST };
+ ExprResult
+ BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
+ SourceLocation RParenLoc, MultiExprArg Args,
+ AtomicExpr::AtomicOp Op,
+ AtomicArgumentOrder ArgOrder = AtomicArgumentOrder::API);
ExprResult
BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc,
ArrayRef<Expr *> Arg, SourceLocation RParenLoc,
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index cbe7e9a8238..19c83d6bac2 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -4473,7 +4473,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
SourceLocation RParenLoc, MultiExprArg Args,
- AtomicExpr::AtomicOp Op) {
+ AtomicExpr::AtomicOp Op,
+ AtomicArgumentOrder ArgOrder) {
// All the non-OpenCL operations take one of the following forms.
// The OpenCL operations take the __c11 forms with one extra argument for
// synchronization scope.
@@ -4754,19 +4755,56 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
IsPassedByAddress = true;
}
+ SmallVector<Expr *, 5> APIOrderedArgs;
+ if (ArgOrder == Sema::AtomicArgumentOrder::AST) {
+ APIOrderedArgs.push_back(Args[0]);
+ switch (Form) {
+ case Init:
+ case Load:
+ APIOrderedArgs.push_back(Args[1]); // Val1/Order
+ break;
+ case LoadCopy:
+ case Copy:
+ case Arithmetic:
+ case Xchg:
+ APIOrderedArgs.push_back(Args[2]); // Val1
+ APIOrderedArgs.push_back(Args[1]); // Order
+ break;
+ case GNUXchg:
+ APIOrderedArgs.push_back(Args[2]); // Val1
+ APIOrderedArgs.push_back(Args[3]); // Val2
+ APIOrderedArgs.push_back(Args[1]); // Order
+ break;
+ case C11CmpXchg:
+ APIOrderedArgs.push_back(Args[2]); // Val1
+ APIOrderedArgs.push_back(Args[4]); // Val2
+ APIOrderedArgs.push_back(Args[1]); // Order
+ APIOrderedArgs.push_back(Args[3]); // OrderFail
+ break;
+ case GNUCmpXchg:
+ APIOrderedArgs.push_back(Args[2]); // Val1
+ APIOrderedArgs.push_back(Args[4]); // Val2
+ APIOrderedArgs.push_back(Args[5]); // Weak
+ APIOrderedArgs.push_back(Args[1]); // Order
+ APIOrderedArgs.push_back(Args[3]); // OrderFail
+ break;
+ }
+ } else
+ APIOrderedArgs.append(Args.begin(), Args.end());
+
// The first argument's non-CV pointer type is used to deduce the type of
// subsequent arguments, except for:
// - weak flag (always converted to bool)
// - memory order (always converted to int)
// - scope (always converted to int)
- for (unsigned i = 0; i != Args.size(); ++i) {
+ for (unsigned i = 0; i != APIOrderedArgs.size(); ++i) {
QualType Ty;
if (i < NumVals[Form] + 1) {
switch (i) {
case 0:
// The first argument is always a pointer. It has a fixed type.
// It is always dereferenced, a nullptr is undefined.
- CheckNonNullArgument(*this, Args[i], ExprRange.getBegin());
+ CheckNonNullArgument(*this, APIOrderedArgs[i], ExprRange.getBegin());
// Nothing else to do: we already know all we want about this pointer.
continue;
case 1:
@@ -4778,14 +4816,16 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
if (Form == Init || (Form == Arithmetic && ValType->isIntegerType()))
Ty = ValType;
else if (Form == Copy || Form == Xchg) {
- if (IsPassedByAddress)
+ if (IsPassedByAddress) {
// The value pointer is always dereferenced, a nullptr is undefined.
- CheckNonNullArgument(*this, Args[i], ExprRange.getBegin());
+ CheckNonNullArgument(*this, APIOrderedArgs[i],
+ ExprRange.getBegin());
+ }
Ty = ByValType;
} else if (Form == Arithmetic)
Ty = Context.getPointerDiffType();
else {
- Expr *ValArg = Args[i];
+ Expr *ValArg = APIOrderedArgs[i];
// The value pointer is always dereferenced, a nullptr is undefined.
CheckNonNullArgument(*this, ValArg, ExprRange.getBegin());
LangAS AS = LangAS::Default;
@@ -4802,7 +4842,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
// The third argument to compare_exchange / GNU exchange is the desired
// value, either by-value (for the C11 and *_n variant) or as a pointer.
if (IsPassedByAddress)
- CheckNonNullArgument(*this, Args[i], ExprRange.getBegin());
+ CheckNonNullArgument(*this, APIOrderedArgs[i], ExprRange.getBegin());
Ty = ByValType;
break;
case 3:
@@ -4817,11 +4857,11 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
InitializedEntity Entity =
InitializedEntity::InitializeParameter(Context, Ty, false);
- ExprResult Arg = Args[i];
+ ExprResult Arg = APIOrderedArgs[i];
Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg);
if (Arg.isInvalid())
return true;
- Args[i] = Arg.get();
+ APIOrderedArgs[i] = Arg.get();
}
// Permute the arguments into a 'consistent' order.
@@ -4830,36 +4870,36 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
switch (Form) {
case Init:
// Note, AtomicExpr::getVal1() has a special case for this atomic.
- SubExprs.push_back(Args[1]); // Val1
+ SubExprs.push_back(APIOrderedArgs[1]); // Val1
break;
case Load:
- SubExprs.push_back(Args[1]); // Order
+ SubExprs.push_back(APIOrderedArgs[1]); // Order
break;
case LoadCopy:
case Copy:
case Arithmetic:
case Xchg:
- SubExprs.push_back(Args[2]); // Order
- SubExprs.push_back(Args[1]); // Val1
+ SubExprs.push_back(APIOrderedArgs[2]); // Order
+ SubExprs.push_back(APIOrderedArgs[1]); // Val1
break;
case GNUXchg:
// Note, AtomicExpr::getVal2() has a special case for this atomic.
- SubExprs.push_back(Args[3]); // Order
- SubExprs.push_back(Args[1]); // Val1
- SubExprs.push_back(Args[2]); // Val2
+ SubExprs.push_back(APIOrderedArgs[3]); // Order
+ SubExprs.push_back(APIOrderedArgs[1]); // Val1
+ SubExprs.push_back(APIOrderedArgs[2]); // Val2
break;
case C11CmpXchg:
- SubExprs.push_back(Args[3]); // Order
- SubExprs.push_back(Args[1]); // Val1
- SubExprs.push_back(Args[4]); // OrderFail
- SubExprs.push_back(Args[2]); // Val2
+ SubExprs.push_back(APIOrderedArgs[3]); // Order
+ SubExprs.push_back(APIOrderedArgs[1]); // Val1
+ SubExprs.push_back(APIOrderedArgs[4]); // OrderFail
+ SubExprs.push_back(APIOrderedArgs[2]); // Val2
break;
case GNUCmpXchg:
- SubExprs.push_back(Args[4]); // Order
- SubExprs.push_back(Args[1]); // Val1
- SubExprs.push_back(Args[5]); // OrderFail
- SubExprs.push_back(Args[2]); // Val2
- SubExprs.push_back(Args[3]); // Weak
+ SubExprs.push_back(APIOrderedArgs[4]); // Order
+ SubExprs.push_back(APIOrderedArgs[1]); // Val1
+ SubExprs.push_back(APIOrderedArgs[5]); // OrderFail
+ SubExprs.push_back(APIOrderedArgs[2]); // Val2
+ SubExprs.push_back(APIOrderedArgs[3]); // Weak
break;
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 9a436e81ec5..9218f9eeb5a 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3308,14 +3308,14 @@ public:
///
/// 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,
+ ExprResult RebuildAtomicExpr(SourceLocation BuiltinLoc, MultiExprArg SubExprs,
AtomicExpr::AtomicOp Op,
SourceLocation RParenLoc) {
// Use this for all of the locations, since we don't know the difference
// between the call and the expr at this point.
SourceRange Range{BuiltinLoc, RParenLoc};
- return getSema().BuildAtomicExpr(Range, Range, RParenLoc, SubExprs, Op);
+ return getSema().BuildAtomicExpr(Range, Range, RParenLoc, SubExprs, Op,
+ Sema::AtomicArgumentOrder::AST);
}
private:
diff --git a/clang/test/AST/atomic-expr.cpp b/clang/test/AST/atomic-expr.cpp
index 550b8d186c3..e7fb6ba833e 100644
--- a/clang/test/AST/atomic-expr.cpp
+++ b/clang/test/AST/atomic-expr.cpp
@@ -3,17 +3,58 @@
template<int N = 0>
void pr43370() {
int arr[2];
- __atomic_store_n(arr, 0, 0);
+ __atomic_store_n(arr, 0, 5);
}
+
+template<int N = 0>
+void foo() {
+ int arr[2];
+ (void)__atomic_compare_exchange_n(arr, arr, 1, 0, 3, 4);
+}
+
void useage(){
pr43370();
+ foo();
}
// CHECK:FunctionTemplateDecl 0x{{[0-9a-f]+}} <{{[^,]+}}, line:7:1> line:4:6 pr43370
// CHECK: AtomicExpr
// CHECK-NEXT: ImplicitCastExpr
// CHECK-SAME: <ArrayToPointerDecay>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-f]+}} <{{[^:]+}}:20> 'int [2]' lvalue Var 0x{{[0-9a-f]+}} 'arr' 'int [2]'
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-f]+}} <{{[^:]+}}:28> 'int' 5
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-f]+}} <{{[^:]+}}:25> 'int' 0
// CHECK:FunctionDecl 0x{{[0-9a-f]+}} <line:4:1, line:7:1> line:4:6 used pr43370
// CHECK: AtomicExpr
// CHECK-NEXT: ImplicitCastExpr
// CHECK-SAME: <ArrayToPointerDecay>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-f]+}} <{{[^:]+}}:20> 'int [2]' lvalue Var 0x{{[0-9a-f]+}} 'arr' 'int [2]'
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-f]+}} <{{[^:]+}}:28> 'int' 5
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-f]+}} <{{[^:]+}}:25> 'int' 0
+
+// CHECK:FunctionTemplateDecl 0x{{[0-9a-f]+}} <line:9:1, line:13:1> line:10:6 foo
+// CHECK: AtomicExpr
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-SAME: <ArrayToPointerDecay>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-f]+}} <{{[^:]+}}:37> 'int [2]' lvalue Var 0x{{[0-9a-f]+}} 'arr' 'int [2]'
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-f]+}} <{{[^:]+}}:53> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-SAME: <ArrayToPointerDecay>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-f]+}} <{{[^:]+}}:42> 'int [2]' lvalue Var 0x{{[0-9a-f]+}} 'arr' 'int [2]'
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-f]+}} <{{[^:]+}}:56> 'int' 4
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-f]+}} <{{[^:]+}}:47> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-f]+}} <{{[^:]+}}:50> 'int' 0
+// CHECK:FunctionDecl 0x{{[0-9a-f]+}} <line:10:1, line:13:1> line:10:6 used foo
+// CHECK: AtomicExpr
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-SAME: <ArrayToPointerDecay>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-f]+}} <{{[^:]+}}:37> 'int [2]' lvalue Var 0x{{[0-9a-f]+}} 'arr' 'int [2]'
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-f]+}} <{{[^:]+}}:53> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-SAME: <ArrayToPointerDecay>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-f]+}} <{{[^:]+}}:42> 'int [2]' lvalue Var 0x{{[0-9a-f]+}} 'arr' 'int [2]'
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-f]+}} <{{[^:]+}}:56> 'int' 4
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-f]+}} <{{[^:]+}}:47> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-f]+}} <{{[^:]+}}:50> 'int' 0
OpenPOWER on IntegriCloud