courbet updated this revision to Diff 385768.
courbet added a comment.

one more spaceship operator fix.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D112453/new/

https://reviews.llvm.org/D112453

Files:
  clang/include/clang/AST/Type.h
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/AST/ast-dump-expr-json.cpp
  clang/test/AST/ast-dump-expr.cpp
  clang/test/AST/ast-dump-lambda.cpp
  clang/test/CXX/over/over.built/ast-20.cpp
  clang/test/CXX/over/over.built/ast.cpp
  clang/test/CXX/over/over.built/p10.cpp
  clang/test/CXX/over/over.built/p11.cpp
  clang/test/CXX/over/over.built/p13.cpp
  clang/test/CXX/over/over.built/p14.cpp
  clang/test/CXX/over/over.built/p18.cpp
  clang/test/CXX/over/over.built/p19.cpp
  clang/test/CXX/over/over.built/p20.cpp
  clang/test/CXX/over/over.built/p22.cpp
  clang/test/CXX/over/over.built/p23.cpp
  clang/test/CXX/over/over.built/p4.cpp
  clang/test/CXX/over/over.built/p5.cpp
  clang/test/CXX/over/over.built/p7.cpp
  clang/test/CXX/over/over.built/spaceship.cpp
  clang/test/Frontend/noderef_templates.cpp
  clang/test/SemaTemplate/dependent-type-identity.cpp

Index: clang/test/SemaTemplate/dependent-type-identity.cpp
===================================================================
--- clang/test/SemaTemplate/dependent-type-identity.cpp
+++ clang/test/SemaTemplate/dependent-type-identity.cpp
@@ -69,6 +69,16 @@
   void f8(typename N::X2<U>::template apply<U> *);
   void f8(typename N::X2<U>::template apply<T> *);
   void f8(typename ::Nalias::X2<type>::template apply<U_type> *); // expected-error{{redeclar}}
+
+  // (17.4.2): If an expression e is type-dependent (17.6.2.2), decltype(e)
+  // denotes a unique dependent type. Two such decltype-specifiers refer to the
+  // same type only if their expressions are equivalent (17.5.6.1)
+  T* a;
+  T* b;
+  using V = decltype(*a);
+  void f9(decltype(*a)); // expected-note{{previous}}
+  void f9(decltype(*b));
+  void f9(V); // expected-error{{redeclar}}
 };
 
 namespace PR6851 {
Index: clang/test/Frontend/noderef_templates.cpp
===================================================================
--- clang/test/Frontend/noderef_templates.cpp
+++ clang/test/Frontend/noderef_templates.cpp
@@ -3,8 +3,8 @@
 #define NODEREF __attribute__((noderef))
 
 template <typename T>
-int func(T NODEREF *a) { // expected-note 2 {{a declared here}}
-  return *a + 1;         // expected-warning 2 {{dereferencing a; was declared with a 'noderef' type}}
+int func(T NODEREF *a) { // expected-note 3 {{a declared here}}
+  return *a + 1;         // expected-warning 3 {{dereferencing a; was declared with a 'noderef' type}}
 }
 
 void func() {
Index: clang/test/CXX/over/over.built/spaceship.cpp
===================================================================
--- clang/test/CXX/over/over.built/spaceship.cpp
+++ clang/test/CXX/over/over.built/spaceship.cpp
@@ -11,11 +11,10 @@
 }
 
 template <typename T>
-void f(int i, float f, int* pi, T* pt, T t) {
+void f(int i, int* pi, T* pt, T t) {
   (void)(i <=> i);
-  (void)(i <=> f); // expected-error {{invalid argument type}}
-  (void)(i <=> pi); // expected-error {{invalid argument type}}
-  (void)(i <=> pt); // expected-error {{invalid argument type}}
+  (void)(i <=> pi); // expected-error {{comparison between pointer and integer}}
+  (void)(i <=> pt); // expected-error {{comparison between pointer and integer}}
   (void)(pi <=> pt);
   (void)(pi <=> t);
 }
Index: clang/test/CXX/over/over.built/p7.cpp
===================================================================
--- clang/test/CXX/over/over.built/p7.cpp
+++ clang/test/CXX/over/over.built/p7.cpp
@@ -3,10 +3,11 @@
 struct A{};
 
 template <typename T>
-void f(int* pi, A* pa, T* pt) {
+void f(int* pi, A* pa, T* pt, T t) {
   (void)*pi;
   (void)*pa;
   (void)*pt;
+  (void)*t;  // `T` might be a `U*`.
 }
 // expected-no-diagnostics
 
Index: clang/test/CXX/over/over.built/p5.cpp
===================================================================
--- clang/test/CXX/over/over.built/p5.cpp
+++ clang/test/CXX/over/over.built/p5.cpp
@@ -1,10 +1,14 @@
 // RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
 
-void f(int i, bool b) {
+template <typename T>
+void f(int i, bool b, T t) {
   (void)--i;
   (void)i--;
 
   (void)--b; // expected-error {{cannot decrement expression of type bool}}
   (void)b--; // expected-error {{cannot decrement expression of type bool}}
+
+  (void)--t;
+  (void)t--;
 }
 
Index: clang/test/CXX/over/over.built/p4.cpp
===================================================================
--- clang/test/CXX/over/over.built/p4.cpp
+++ clang/test/CXX/over/over.built/p4.cpp
@@ -1,10 +1,14 @@
 // RUN: %clang_cc1 -std=c++17 -verify %s -Wno-tautological-compare
 
-void f(int i, bool b) {
+template <typename T>
+void f(int i, bool b, T t) {
   (void)++i;
   (void)i++;
 
   (void)++b; // expected-error {{ISO C++17 does not allow incrementing expression of type bool}}
   (void)b++; // expected-error {{ISO C++17 does not allow incrementing expression of type bool}}
+
+  (void)++t;
+  (void)t++;
 }
 
Index: clang/test/CXX/over/over.built/p23.cpp
===================================================================
--- clang/test/CXX/over/over.built/p23.cpp
+++ clang/test/CXX/over/over.built/p23.cpp
@@ -6,41 +6,41 @@
   f %= 3;  // expected-error {{invalid operands}}
   b %= 3;
   pi %= 3; // expected-error {{invalid operands}}
-  pt %= 3; // FIXME
+  pt %= 3; // expected-error {{invalid operands}}
   t %= 3;
 
   i &= 3;
   f &= 3;  // expected-error {{invalid operands}}
   b &= 3;
   pi &= 3; // expected-error {{invalid operands}}
-  pt &= 3; // FIXME
+  pt &= 3; // expected-error {{invalid operands}}
   t &= 3;
 
   i ^= 3;
   f ^= 3;  // expected-error {{invalid operands}}
   b ^= 3;
   pi ^= 3; // expected-error {{invalid operands}}
-  pt ^= 3; // FIXME
+  pt ^= 3; // expected-error {{invalid operands}}
   t ^= 3;
 
   i |= 3;
   f |= 3;  // expected-error {{invalid operands}}
   b |= 3;
   pi |= 3; // expected-error {{invalid operands}}
-  pt |= 3; // FIXME
+  pt |= 3; // expected-error {{invalid operands}}
   t |= 3;
 
   i <<= 3;
   f <<= 3;  // expected-error {{invalid operands}}
   b <<= 3;
   pi <<= 3; // expected-error {{invalid operands}}
-  pt <<= 3; // FIXME
+  pt <<= 3; // expected-error {{invalid operands}}
   t <<= 3;
 
   i >>= 3;
   f >>= 3;  // expected-error {{invalid operands}}
   b >>= 3;
   pi >>= 3; // expected-error {{invalid operands}}
-  pt >>= 3; // FIXME
+  pt >>= 3; // expected-error {{invalid operands}}
   t >>= 3;
 }
Index: clang/test/CXX/over/over.built/p22.cpp
===================================================================
--- clang/test/CXX/over/over.built/p22.cpp
+++ clang/test/CXX/over/over.built/p22.cpp
@@ -6,7 +6,7 @@
   pi += pi; // expected-error {{invalid operands}}
   pt += 3;
   pi += t;
-  pi += pt; // FIXME
-  pt += pi; //FIXME
-  pt += pt; //FIXME
+  pi += pt; // expected-error {{invalid operands}}
+  pt += pi; // expected-error {{invalid operands}}
+  pt += pt; // expected-error {{invalid operands}}
 }
Index: clang/test/CXX/over/over.built/p20.cpp
===================================================================
--- clang/test/CXX/over/over.built/p20.cpp
+++ clang/test/CXX/over/over.built/p20.cpp
@@ -1,12 +1,15 @@
 // RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
 
-template <typename T, typename U>
-void f(int* pi, float* pf, T* pt, U* pu, T t) {
+template <typename T>
+void f(int i, int* pi, T* pt, T t) {
+  i = i;
   pi = pi;
-  pi = pf; // expected-error {{incompatible pointer types}}
-  pi = pt;
-  pu = pi;
-  pu = pt;
-  pi = t;
-  pu = t;
+  pt = pt;
+  i = pi;   // expected-error {{incompatible pointer to integer}}
+  i = pt;   // FIXME
+  pi = i;   // expected-error {{incompatible integer to pointer}}
+  pt = i;   // FIXME
+  pi = pt;  // Checked during instantiation.
+  pi = t;   // Checked during instantiation.
 }
+
Index: clang/test/CXX/over/over.built/p19.cpp
===================================================================
--- clang/test/CXX/over/over.built/p19.cpp
+++ clang/test/CXX/over/over.built/p19.cpp
@@ -9,7 +9,7 @@
   i -= i;
   i -= f;
   i -= pi; // expected-error {{invalid operands}}
-  i -= pt; // FIXME
+  i -= pt; // expected-error {{invalid operands}}
   i -= t;
 
   f = f;
@@ -19,6 +19,6 @@
   f -= f;
   f -= i;
   f -= pi; // expected-error {{invalid operands}}
-  f -= pt; // FIXME
+  f -= pt; // expected-error {{invalid operands}}
   f -= t;
 }
Index: clang/test/CXX/over/over.built/p18.cpp
===================================================================
--- clang/test/CXX/over/over.built/p18.cpp
+++ clang/test/CXX/over/over.built/p18.cpp
@@ -6,77 +6,77 @@
   (void)(f % 3);  // expected-error {{invalid operands}}
   (void)(b % 3);
   (void)(pi % 3); // expected-error {{invalid operands}}
-  (void)(pt % 3); // FIXME
+  (void)(pt % 3); // expected-error {{invalid operands}}
   (void)(t % 3);
   (void)(3 % i);
   (void)(3 % f);  // expected-error {{invalid operands}}
   (void)(3 % b);
   (void)(3 % pi); // expected-error {{invalid operands}}
-  (void)(3 % pt); // FIXME
+  (void)(3 % pt); // expected-error {{invalid operands}}
   (void)(3 % t);
 
   (void)(i & 3);
   (void)(f & 3);  // expected-error {{invalid operands}}
   (void)(b & 3);
   (void)(pi & 3); // expected-error {{invalid operands}}
-  (void)(pt & 3); // FIXME
+  (void)(pt & 3); // expected-error {{invalid operands}}
   (void)(t & 3);
   (void)(3 & i);
   (void)(3 & f);  // expected-error {{invalid operands}}
   (void)(3 & b);
   (void)(3 & pi); // expected-error {{invalid operands}}
-  (void)(3 & pt); // FIXME
+  (void)(3 & pt); // expected-error {{invalid operands}}
   (void)(3 & t);
 
   (void)(i ^ 3);
   (void)(f ^ 3);  // expected-error {{invalid operands}}
   (void)(b ^ 3);
   (void)(pi ^ 3); // expected-error {{invalid operands}}
-  (void)(pt ^ 3); // FIXME
+  (void)(pt ^ 3); // expected-error {{invalid operands}}
   (void)(t ^ 3);
   (void)(3 ^ i);
   (void)(3 ^ f);  // expected-error {{invalid operands}}
   (void)(3 ^ b);
   (void)(3 ^ pi); // expected-error {{invalid operands}}
-  (void)(3 ^ pt); // FIXME
+  (void)(3 ^ pt); // expected-error {{invalid operands}}
   (void)(3 ^ t);
 
   (void)(i | 3);
   (void)(f | 3);  // expected-error {{invalid operands}}
   (void)(b | 3);
   (void)(pi | 3); // expected-error {{invalid operands}}
-  (void)(pt | 3); // FIXME
+  (void)(pt | 3); // expected-error {{invalid operands}}
   (void)(t | 3);
   (void)(3 | i);
   (void)(3 | f);  // expected-error {{invalid operands}}
   (void)(3 | b);
   (void)(3 | pi); // expected-error {{invalid operands}}
-  (void)(3 | pt); // FIXME
+  (void)(3 | pt); // expected-error {{invalid operands}}
   (void)(3 | t);
 
   (void)(i << 3);
   (void)(f << 3);  // expected-error {{invalid operands}}
   (void)(b << 3);
   (void)(pi << 3); // expected-error {{invalid operands}}
-  (void)(pt << 3); // FIXME
+  (void)(pt << 3); // expected-error {{invalid operands}}
   (void)(t << 3);
   (void)(3 << i);
   (void)(3 << f);  // expected-error {{invalid operands}}
   (void)(3 << b);
   (void)(3 << pi); // expected-error {{invalid operands}}
-  (void)(3 << pt); // FIXME
+  (void)(3 << pt); // expected-error {{invalid operands}}
   (void)(3 << t);
 
   (void)(i >> 3);
   (void)(f >> 3);  // expected-error {{invalid operands}}
   (void)(b >> 3);
   (void)(pi >> 3); // expected-error {{invalid operands}}
-  (void)(pt >> 3); // FIXME
+  (void)(pt >> 3); // expected-error {{invalid operands}}
   (void)(t >> 3);
   (void)(3 >> i);
   (void)(3 >> f);  // expected-error {{invalid operands}}
   (void)(3 >> b);
   (void)(3 >> pi); // expected-error {{invalid operands}}
-  (void)(3 >> pt); // FIXME
+  (void)(3 >> pt); // expected-error {{invalid operands}}
   (void)(3 >> t);
 }
Index: clang/test/CXX/over/over.built/p14.cpp
===================================================================
--- clang/test/CXX/over/over.built/p14.cpp
+++ clang/test/CXX/over/over.built/p14.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
 
 template <typename T>
-void f(int* pi, T* pt) {
+void f(int* pi, T* pt, T t) {
   (void)(pi+3);
   (void)(3+pi);
   (void)(pi-3);
@@ -13,5 +13,11 @@
   (void)(pt-3);
   (void)(pt[3]);
   (void)(3[pt]);
+
+  (void)(t+3);
+  (void)(3+t);
+  (void)(t-3);
+  (void)(t[3]);
+  (void)(3[t]);
 }
 // expected-no-diagnostics
Index: clang/test/CXX/over/over.built/p13.cpp
===================================================================
--- clang/test/CXX/over/over.built/p13.cpp
+++ clang/test/CXX/over/over.built/p13.cpp
@@ -1,40 +1,45 @@
 // RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
 
 template <typename T>
-void f(int i, float f, bool b, char c, int* pi, T* pt) {
+void f(int i, float f, bool b, char c, int* pi, T* pt, T t) {
   (void)(i*i);
   (void)(i*f);
   (void)(i*b);
   (void)(i*c);
   (void)(i*pi); // expected-error {{invalid operands to binary expression}}
-  (void)(i*pt); // FIXME
+  (void)(i*pt); // expected-error {{invalid operands to binary expression}}
+  (void)(i*t);
 
   (void)(i/i);
   (void)(i/f);
   (void)(i/b);
   (void)(i/c);
   (void)(i/pi); // expected-error {{invalid operands to binary expression}}
-  (void)(i/pt); // FIXME
+  (void)(i/pt); // expected-error {{invalid operands to binary expression}}
+  (void)(i/t);
 
   (void)(i-i);
   (void)(i-f);
   (void)(i-b);
   (void)(i-c);
   (void)(i-pi); // expected-error {{invalid operands to binary expression}}
-  (void)(i-pt); // FIXME
+  (void)(i-pt); // expected-error {{invalid operands to binary expression}}
+  (void)(i-t);
 
   (void)(i<i);
   (void)(i<f);
   (void)(i<b);
   (void)(i<c);
   (void)(i<pi); // expected-error {{comparison between pointer and integer}}
-  (void)(i<pt); // FIXME
+  (void)(i<pt); // expected-error {{comparison between pointer and integer}}
+  (void)(i<t);
 
   (void)(i==i);
   (void)(i==f);
   (void)(i==b);
   (void)(i==c);
   (void)(i==pi); // expected-error {{comparison between pointer and integer}}
-  (void)(i==pt); // FIXME
+  (void)(i==pt); // expected-error {{comparison between pointer and integer}}
+  (void)(i==t);
 }
 
Index: clang/test/CXX/over/over.built/p11.cpp
===================================================================
--- clang/test/CXX/over/over.built/p11.cpp
+++ clang/test/CXX/over/over.built/p11.cpp
@@ -1,12 +1,13 @@
 // RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
 
 template <typename T>
-void f(int i, float f, bool b, char c, int* pi, T* pt) {
+void f(int i, float f, bool b, char c, int* pi, T* pt, T t) {
   (void)~i;
   (void)~f; // expected-error {{invalid argument type}}
   (void)~b;
   (void)~c;
   (void)~pi; // expected-error {{invalid argument type}}
-  (void)~pt; // FIXME: we should be able to give an error here.
+  (void)~pt; // expected-error {{invalid argument type}}
+  (void)~t;
 }
 
Index: clang/test/CXX/over/over.built/p10.cpp
===================================================================
--- clang/test/CXX/over/over.built/p10.cpp
+++ clang/test/CXX/over/over.built/p10.cpp
@@ -3,7 +3,7 @@
 struct A{};
 
 template <typename T>
-void f(int i, float f, bool b, char c, int* pi, A* pa, T* pt) {
+void f(int i, float f, bool b, char c, int* pi, A* pa, T* pt, T t) {
   (void)+i;
   (void)-i;
   (void)+f;
@@ -12,9 +12,11 @@
   (void)-b;
   (void)+c;
   (void)-c;
+  (void)+t;
+  (void)-t;
 
   (void)-pi; // expected-error {{invalid argument type}}
   (void)-pa; // expected-error {{invalid argument type}}
-  (void)-pt; // FIXME: we should be able to give an error here.
+  (void)-pt; // expected-error {{invalid argument type}}
 }
 
Index: clang/test/CXX/over/over.built/ast.cpp
===================================================================
--- clang/test/CXX/over/over.built/ast.cpp
+++ clang/test/CXX/over/over.built/ast.cpp
@@ -4,38 +4,46 @@
 
 template <typename T, typename U>
 auto Test(T* pt, U* pu) {
-  // CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '*'
+  // CHECK: UnaryOperator {{.*}} 'T' lvalue prefix '*'
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <LValueToRValue>
   // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
   (void)*pt;
 
-  // CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '++'
+  // CHECK: UnaryOperator {{.*}} 'T *' lvalue prefix '++'
   // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
   (void)(++pt);
 
-  // CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '+'
+  // CHECK: UnaryOperator {{.*}} 'T *' prefix '+'
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <LValueToRValue>
   // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
   (void)(+pt);
 
-  // CHECK: BinaryOperator {{.*}} '<dependent type>' '+'
+  // CHECK: BinaryOperator {{.*}} 'T *' '+'
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <LValueToRValue>
   // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
   // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3
   (void)(pt + 3);
 
-  // CHECK: BinaryOperator {{.*}} '<dependent type>' '-'
+  // CHECK: BinaryOperator {{.*}} 'long' '-'
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <LValueToRValue>
   // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <LValueToRValue>
   // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
   (void)(pt - pt);
 
-  // CHECK: BinaryOperator {{.*}} '<dependent type>' '-'
+  // CHECK: BinaryOperator {{.*}} 'long' '-'
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <LValueToRValue>
   // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} 'U *' <LValueToRValue>
   // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *'
   (void)(pt - pu);
 
-  // CHECK: BinaryOperator {{.*}} '<dependent type>' '=='
+  // CHECK: BinaryOperator {{.*}} 'bool' '=='
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <LValueToRValue>
   // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} 'U *' <LValueToRValue>
   // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *'
   (void)(pt == pu);
 
 }
 
-
Index: clang/test/CXX/over/over.built/ast-20.cpp
===================================================================
--- clang/test/CXX/over/over.built/ast-20.cpp
+++ clang/test/CXX/over/over.built/ast-20.cpp
@@ -13,7 +13,9 @@
 template <typename T, typename U>
 auto Test(T* pt, U* pu) {
   // CHECK: BinaryOperator {{.*}} '<dependent type>' '<=>'
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <LValueToRValue>
   // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
+  // CHECK-NEXT: ImplicitCastExpr {{.*}} 'U *' <LValueToRValue>
   // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *'
   (void)(pt <=> pu);
 
Index: clang/test/AST/ast-dump-lambda.cpp
===================================================================
--- clang/test/AST/ast-dump-lambda.cpp
+++ clang/test/AST/ast-dump-lambda.cpp
@@ -81,7 +81,7 @@
 // CHECK-NEXT:    |         | | `-CompoundStmt {{.*}} <col:15, col:16>
 // CHECK-NEXT:    |         | `-FieldDecl {{.*}} <col:8> col:8{{( imported)?}} implicit 'V'
 // CHECK-NEXT:    |         |-ParenListExpr {{.*}} <col:8> 'NULL TYPE'
-// CHECK-NEXT:    |         | `-UnaryOperator {{.*}} <col:8> '<dependent type>' prefix '*' cannot overflow
+// CHECK-NEXT:    |         | `-UnaryOperator {{.*}} <col:8> 'V' lvalue prefix '*' cannot overflow
 // CHECK-NEXT:    |         |   `-CXXThisExpr {{.*}} <col:8> 'V *' this
 // CHECK-NEXT:    |         `-CompoundStmt {{.*}} <col:15, col:16>
 // CHECK-NEXT:    |-DeclStmt {{.*}} <line:22:3, col:11>
Index: clang/test/AST/ast-dump-expr.cpp
===================================================================
--- clang/test/AST/ast-dump-expr.cpp
+++ clang/test/AST/ast-dump-expr.cpp
@@ -281,7 +281,7 @@
       // CHECK-NEXT: CompoundStmt
       // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:8> col:8 implicit 'V'
       // CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} <col:8> 'NULL TYPE'
-      // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:8> '<dependent type>' prefix '*' cannot overflow
+      // CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:8> 'V' lvalue prefix '*' cannot overflow
       // CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} <col:8> 'V *' this
     }
   };
Index: clang/test/AST/ast-dump-expr-json.cpp
===================================================================
--- clang/test/AST/ast-dump-expr-json.cpp
+++ clang/test/AST/ast-dump-expr-json.cpp
@@ -4267,9 +4267,9 @@
 // CHECK-NEXT:                     }
 // CHECK-NEXT:                    },
 // CHECK-NEXT:                    "type": {
-// CHECK-NEXT:                     "qualType": "<dependent type>"
+// CHECK-NEXT:                     "qualType": "V"
 // CHECK-NEXT:                    },
-// CHECK-NEXT:                    "valueCategory": "prvalue",
+// CHECK-NEXT:                    "valueCategory": "lvalue",
 // CHECK-NEXT:                    "isPostfix": false,
 // CHECK-NEXT:                    "opcode": "*",
 // CHECK-NEXT:                    "canOverflow": false,
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -6603,6 +6603,14 @@
   assert(!T1->isNullPtrType() && !T2->isNullPtrType() &&
          "nullptr_t should be a null pointer constant");
 
+  if (T1->getPointeeType()->isDependentType() ||
+      T2->getPointeeType()->isDependentType()) {
+    // We can't do the conversion now.
+    // FIXME: We know that the composite pointer type is a pointer type, return
+    // pointer to dependant type.
+    return Context.DependentTy;
+  }
+
   struct Step {
     enum Kind { Pointer, ObjCPointer, MemberPointer, Array } K;
     // Qualifiers to apply under the step kind.
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -644,8 +644,7 @@
   // expressions of certain types in C++.
   if (getLangOpts().CPlusPlus &&
       (E->getType() == Context.OverloadTy ||
-       T->isDependentType() ||
-       T->isRecordType()))
+       (T->isDependentType() && !T->isPointerType()) || T->isRecordType()))
     return E;
 
   // The C standard is actually really unclear on this point, and
@@ -10544,6 +10543,9 @@
   if (!ResType->isAnyPointerType()) return true;
 
   QualType PointeeTy = ResType->getPointeeType();
+  if (PointeeTy->isDependentType()) {
+    return true;
+  }
   if (PointeeTy->isVoidType()) {
     diagnoseArithmeticOnVoidPointer(S, Loc, Operand);
     return !S.getLangOpts().CPlusPlus;
@@ -10610,9 +10612,11 @@
     return !S.getLangOpts().CPlusPlus;
   }
 
-  if (isLHSPointer && checkArithmeticIncompletePointerType(S, Loc, LHSExpr))
+  if (isLHSPointer && !LHSPointeeTy->isDependentType() &&
+      checkArithmeticIncompletePointerType(S, Loc, LHSExpr))
     return false;
-  if (isRHSPointer && checkArithmeticIncompletePointerType(S, Loc, RHSExpr))
+  if (isRHSPointer && !RHSPointeeTy->isDependentType() &&
+      checkArithmeticIncompletePointerType(S, Loc, RHSExpr))
     return false;
 
   return true;
@@ -10896,7 +10900,9 @@
 
       if (getLangOpts().CPlusPlus) {
         // Pointee types must be the same: C++ [expr.add]
-        if (!Context.hasSameUnqualifiedType(lpointee, rpointee)) {
+        // If pointees are dependent types, we defer this to later.
+        if (!lpointee->isDependentType() && !rpointee->isDependentType() &&
+            !Context.hasSameUnqualifiedType(lpointee, rpointee)) {
           diagnosePointerIncompatibility(*this, Loc, LHS.get(), RHS.get());
         }
       } else {
@@ -10927,7 +10933,8 @@
       // The pointee type may have zero size.  As an extension, a structure or
       // union may have zero size or an array may have zero length.  In this
       // case subtraction does not make sense.
-      if (!rpointee->isVoidType() && !rpointee->isFunctionType()) {
+      if (!rpointee->isDependentType() && !rpointee->isVoidType() &&
+          !rpointee->isFunctionType()) {
         CharUnits ElementSize = Context.getTypeSizeInChars(rpointee);
         if (ElementSize.isZero()) {
           Diag(Loc,diag::warn_sub_ptr_zero_size_types)
@@ -11855,6 +11862,9 @@
   auto computeResultTy = [&]() {
     if (Opc != BO_Cmp)
       return Context.getLogicalOperationType();
+    if (LHS.get()->getType()->isDependentType() ||
+        RHS.get()->getType()->isDependentType())
+      return QualType(Context.DependentTy);
     assert(getLangOpts().CPlusPlus);
     assert(Context.hasSameType(LHS.get()->getType(), RHS.get()->getType()));
 
@@ -13399,7 +13409,7 @@
                                                ExprObjectKind &OK,
                                                SourceLocation OpLoc,
                                                bool IsInc, bool IsPrefix) {
-  if (Op->isTypeDependent())
+  if (Op->isTypeDependent() && !Op->getType()->isPointerType())
     return S.Context.DependentTy;
 
   QualType ResType = Op->getType();
@@ -13811,7 +13821,7 @@
 /// CheckIndirectionOperand - Type check unary indirection (prefix '*').
 static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
                                         SourceLocation OpLoc) {
-  if (Op->isTypeDependent())
+  if (Op->isTypeDependent() && !Op->getType()->isPointerType())
     return S.Context.DependentTy;
 
   ExprResult ConvResult = S.UsualUnaryConversions(Op);
@@ -14172,7 +14182,11 @@
 
   switch (Opc) {
   case BO_Assign:
-    ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType());
+    if (getLangOpts().CPlusPlus &&
+        (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent()))
+      ResultTy = LHSExpr->getType();
+    else
+      ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType());
     if (getLangOpts().CPlusPlus &&
         LHS.get()->getObjectKind() != OK_ObjCProperty) {
       VK = LHS.get()->getValueKind();
@@ -14248,7 +14262,8 @@
   case BO_Cmp:
     ConvertHalfVec = true;
     ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc);
-    assert(ResultTy.isNull() || ResultTy->getAsCXXRecordDecl());
+    assert(ResultTy.isNull() || ResultTy->isDependentType() ||
+           ResultTy->getAsCXXRecordDecl());
     break;
   case BO_And:
     checkObjCPointerIntrospection(*this, LHS, RHS, OpLoc);
@@ -14733,21 +14748,15 @@
   }
 
   if (getLangOpts().CPlusPlus) {
-    // If either expression is type-dependent, always build an
-    // overloaded op.
-    if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())
-      return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
-
-    // Otherwise, build an overloaded op if either expression has an
+    // Build an overloaded op if either expression has an
     // overloadable type.
     if (LHSExpr->getType()->isOverloadableType() ||
         RHSExpr->getType()->isOverloadableType())
       return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
   }
 
-  if (getLangOpts().RecoveryAST &&
+  if (!getLangOpts().CPlusPlus && getLangOpts().RecoveryAST &&
       (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())) {
-    assert(!getLangOpts().CPlusPlus);
     assert((LHSExpr->containsErrors() || RHSExpr->containsErrors()) &&
            "Should only occur in error-recovery path.");
     if (BinaryOperator::isCompoundAssignmentOp(Opc))
@@ -14864,7 +14873,7 @@
     if (ConvertHalfVec)
       Input = convertVector(Input.get(), Context.FloatTy, *this);
     resultType = Input.get()->getType();
-    if (resultType->isDependentType())
+    if (resultType->isDependentType() && !resultType->isPointerType())
       break;
     if (resultType->isArithmeticType()) // C99 6.5.3.3p1
       break;
@@ -14887,7 +14896,7 @@
     if (Input.isInvalid())
       return ExprError();
     resultType = Input.get()->getType();
-    if (resultType->isDependentType())
+    if (resultType->isDependentType() && !resultType->isPointerType())
       break;
     // C99 6.5.3.3p1. We allow complex int and float as a GCC extension.
     if (resultType->isComplexType() || resultType->isComplexIntegerType())
@@ -14921,7 +14930,7 @@
       resultType = Context.FloatTy;
     }
 
-    if (resultType->isDependentType())
+    if (resultType->isDependentType() && !resultType->isPointerType())
       break;
     if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) {
       // C99 6.5.3.3p1: ok, fallthrough;
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -7082,6 +7082,13 @@
 /// Determines whether this is a type for which one can define
 /// an overloaded operator.
 inline bool Type::isOverloadableType() const {
+  // (16.5.6): An operator function [...] parameter whose type is a class,
+  // a reference to a class, an enumeration, or a reference to an
+  // enumeration.
+  if (isPointerType()) {
+    // If the type is a pointer, it cannot be overloaded.
+    return false;
+  }
   return isDependentType() || isRecordType() || isEnumeralType();
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to