From dbbfaa60fd51404ce1710705bb096ee214dc5622 Mon Sep 17 00:00:00 2001
From: Alex Lorenz <arphaman@gmail.com>
Date: Thu, 19 Jan 2017 17:17:57 +0000
Subject: [PATCH] [Sema] Fix PR28181 by avoiding calling BuildOverloadedBinOp
 in C mode

rdar://28532840

Differential Revision: https://reviews.llvm.org/D25213


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@292497 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Sema/SemaExpr.cpp | 11 +++++------
 test/Sema/PR28181.c   | 13 +++++++++++++
 2 files changed, 18 insertions(+), 6 deletions(-)
 create mode 100644 test/Sema/PR28181.c

diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 7d72b7ede82..388420cc1ba 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -11505,7 +11505,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
       return checkPseudoObjectAssignment(S, OpLoc, Opc, LHSExpr, RHSExpr);
 
     // Don't resolve overloads if the other type is overloadable.
-    if (pty->getKind() == BuiltinType::Overload) {
+    if (getLangOpts().CPlusPlus && pty->getKind() == BuiltinType::Overload) {
       // We can't actually test that if we still have a placeholder,
       // though.  Fortunately, none of the exceptions we see in that
       // code below are valid when the LHS is an overload set.  Note
@@ -11530,17 +11530,16 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
     // An overload in the RHS can potentially be resolved by the type
     // being assigned to.
     if (Opc == BO_Assign && pty->getKind() == BuiltinType::Overload) {
-      if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())
-        return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
-
-      if (LHSExpr->getType()->isOverloadableType())
+      if (getLangOpts().CPlusPlus &&
+          (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent() ||
+           LHSExpr->getType()->isOverloadableType()))
         return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
 
       return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr);
     }
 
     // Don't resolve overloads if the other type is overloadable.
-    if (pty->getKind() == BuiltinType::Overload &&
+    if (getLangOpts().CPlusPlus && pty->getKind() == BuiltinType::Overload &&
         LHSExpr->getType()->isOverloadableType())
       return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
 
diff --git a/test/Sema/PR28181.c b/test/Sema/PR28181.c
new file mode 100644
index 00000000000..3410f466fc7
--- /dev/null
+++ b/test/Sema/PR28181.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct spinlock_t {
+  int lock;
+} audit_skb_queue;
+
+void fn1() {
+  audit_skb_queue = (lock); // expected-error {{use of undeclared identifier 'lock'; did you mean 'long'?}}
+}                           // expected-error@-1 {{assigning to 'struct spinlock_t' from incompatible type '<overloaded function type>'}}
+
+void fn2() {
+  audit_skb_queue + (lock); // expected-error {{use of undeclared identifier 'lock'; did you mean 'long'?}}
+}                           // expected-error@-1 {{reference to overloaded function could not be resolved; did you mean to call it?}}
-- 
GitLab