[PATCH] D49945: [Fixed Point Arithmetic] Fix for FixedPointValueToString

2018-08-06 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan marked an inline comment as done.
leonardchan added inline comments.



Comment at: lib/AST/Expr.cpp:788
   FixedPointValueToString(
-  S, llvm::APSInt::getUnsigned(getValue().getZExtValue()), Scale, Radix);
+  S, llvm::APSInt::getUnsigned(getValue().getZExtValue()), Scale);
   return S.str();

ebevhan wrote:
> Unrelated to this patch specifically, but using `getZExtValue` here is a bit 
> limiting.
I'll make another small patch to change this since should also do signed values 
now,


Repository:
  rC Clang

https://reviews.llvm.org/D49945



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D49945: [Fixed Point Arithmetic] Fix for FixedPointValueToString

2018-08-06 Thread Leonard Chan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
leonardchan marked an inline comment as done.
Closed by commit rC339026: [Fixed Point Arithmetic] Fix for 
FixedPointValueToString (authored by leonardchan, committed by ).

Repository:
  rC Clang

https://reviews.llvm.org/D49945

Files:
  include/clang/AST/Type.h
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Type.cpp
  test/Frontend/fixed_point_to_string.c
  unittests/Frontend/CMakeLists.txt
  unittests/Frontend/FixedPointString.cpp

Index: test/Frontend/fixed_point_to_string.c
===
--- test/Frontend/fixed_point_to_string.c
+++ test/Frontend/fixed_point_to_string.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -ast-dump -ffixed-point %s | FileCheck %s
+// RUN: %clang_cc1 -ast-dump -ffixed-point -fpadding-on-unsigned-fixed-point %s | FileCheck %s
+
+/**
+ * Check the same values are printed in the AST regardless of if unsigned types
+ * have the same number of fractional bits as signed types.
+ */
+
+unsigned short _Accum u_short_accum = 0.5uhk;
+unsigned _Accum u_accum = 0.5uk;
+unsigned long _Accum u_long_accum = 0.5ulk;
+unsigned short _Fract u_short_fract = 0.5uhr;
+unsigned _Fract u_fract = 0.5ur;
+unsigned long _Fract u_long_fract = 0.5ulr;
+
+//CHECK: FixedPointLiteral {{.*}} 'unsigned short _Accum' 0.5
+//CHECK: FixedPointLiteral {{.*}} 'unsigned _Accum' 0.5
+//CHECK: FixedPointLiteral {{.*}} 'unsigned long _Accum' 0.5
+//CHECK: FixedPointLiteral {{.*}} 'unsigned short _Fract' 0.5
+//CHECK: FixedPointLiteral {{.*}} 'unsigned _Fract' 0.5
+//CHECK: FixedPointLiteral {{.*}} 'unsigned long _Fract' 0.5
Index: lib/AST/Type.cpp
===
--- lib/AST/Type.cpp
+++ lib/AST/Type.cpp
@@ -4032,17 +4032,26 @@
 }
 
 void clang::FixedPointValueToString(SmallVectorImpl &Str,
-const llvm::APSInt &Val, unsigned Scale,
-unsigned Radix) {
-  llvm::APSInt ScaleVal = llvm::APSInt::getUnsigned(1ULL << Scale);
-  llvm::APSInt IntPart = Val / ScaleVal;
-  llvm::APSInt FractPart = Val % ScaleVal;
-  llvm::APSInt RadixInt = llvm::APSInt::getUnsigned(Radix);
+llvm::APSInt Val, unsigned Scale) {
+  if (Val.isSigned() && Val.isNegative() && Val != -Val) {
+Val = -Val;
+Str.push_back('-');
+  }
+
+  llvm::APSInt IntPart = Val >> Scale;
+
+  // Add 4 digits to hold the value after multiplying 10 (the radix)
+  unsigned Width = Val.getBitWidth() + 4;
+  llvm::APInt FractPart = Val.zextOrTrunc(Scale).zext(Width);
+  llvm::APInt FractPartMask = llvm::APInt::getAllOnesValue(Scale).zext(Width);
+  llvm::APInt RadixInt = llvm::APInt(Width, 10);
 
-  IntPart.toString(Str, Radix);
+  IntPart.toString(Str, /*radix=*/10);
   Str.push_back('.');
   do {
-(FractPart * RadixInt / ScaleVal).toString(Str, Radix);
-FractPart = (FractPart * RadixInt) % ScaleVal;
-  } while (FractPart.getExtValue());
+(FractPart * RadixInt)
+.lshr(Scale)
+.toString(Str, /*radix=*/10, Val.isSigned());
+FractPart = (FractPart * RadixInt) & FractPartMask;
+  } while (FractPart != 0);
 }
Index: lib/AST/Expr.cpp
===
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -785,7 +785,7 @@
   // which is 43 characters.
   SmallString<64> S;
   FixedPointValueToString(
-  S, llvm::APSInt::getUnsigned(getValue().getZExtValue()), Scale, Radix);
+  S, llvm::APSInt::getUnsigned(getValue().getZExtValue()), Scale);
   return S.str();
 }
 
Index: lib/AST/ExprConstant.cpp
===
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -9698,8 +9698,7 @@
   if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow()) {
 SmallString<64> S;
 FixedPointValueToString(S, Value,
-Info.Ctx.getTypeInfo(E->getType()).Width,
-/*Radix=*/10);
+Info.Ctx.getTypeInfo(E->getType()).Width);
 Info.CCEDiag(E, diag::note_constexpr_overflow) << S << E->getType();
 if (Info.noteUndefinedBehavior()) return false;
   }
Index: unittests/Frontend/FixedPointString.cpp
===
--- unittests/Frontend/FixedPointString.cpp
+++ unittests/Frontend/FixedPointString.cpp
@@ -0,0 +1,107 @@
+#include "clang/AST/Type.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/SmallString.h"
+#include "gtest/gtest.h"
+
+using clang::FixedPointValueToString;
+using llvm::APSInt;
+using llvm::SmallString;
+
+namespace {
+
+TEST(FixedPointString, DifferentTypes) {
+  SmallString<64> S;
+  FixedPointValueToString(S, APSInt::get(320), 7);
+  ASSERT_STREQ(S.c_str(), "2.5");
+
+  S.clear();
+  FixedPointValueToString(S, APSInt::get(0), 7);
+  ASSERT_STREQ(S.c_str(), "0.0")

[PATCH] D50278: [Sema] Fix for crash on conditional operation with address_space pointer

2018-08-06 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 159315.
leonardchan added reviewers: ebevhan, rjmccall.
leonardchan removed a subscriber: ebevhan.
leonardchan added a comment.

- Changed diff such that an error is dumped instead. The code shouldn't compile 
in the first place since it involves conversion between pointers from different 
address_spaces.


Repository:
  rC Clang

https://reviews.llvm.org/D50278

Files:
  lib/Sema/SemaExpr.cpp
  test/Sema/address_spaces.c
  test/Sema/conditional-expr.c


Index: test/Sema/conditional-expr.c
===
--- test/Sema/conditional-expr.c
+++ test/Sema/conditional-expr.c
@@ -74,9 +74,12 @@
   int __attribute__((address_space(2))) *adr2;
   int __attribute__((address_space(3))) *adr3;
   test0 ? adr2 : adr3; // expected-warning {{pointer type mismatch}} 
expected-warning {{expression result unused}}
+   // expected-error@-1{{converting 
'__attribute__((address_space(2))) int *' to type 'void *' changes address 
space of pointer}}
+   // expected-error@-2{{converting 
'__attribute__((address_space(3))) int *' to type 'void *' changes address 
space of pointer}}
 
   // Make sure address-space mask ends up in the result type
   (test0 ? (test0 ? adr2 : adr2) : nonconst_int); // expected-warning 
{{pointer type mismatch}} expected-warning {{expression result unused}}
+  // 
expected-error@-1{{converting '__attribute__((address_space(2))) int *' to type 
'void *' changes address space of pointer}}
 }
 
 int Postgresql() {
Index: test/Sema/address_spaces.c
===
--- test/Sema/address_spaces.c
+++ test/Sema/address_spaces.c
@@ -72,4 +72,6 @@
 // Clang extension doesn't forbid operations on pointers to different address 
spaces.
 char* cmp(_AS1 char *x,  _AS2 char *y) {
   return x < y ? x : y; // expected-warning {{pointer type mismatch 
('__attribute__((address_space(1))) char *' and 
'__attribute__((address_space(2))) char *')}}
+// expected-error@-1{{converting 
'__attribute__((address_space(1))) char *' to type 'void *' changes address 
space of pointer}}
+// expected-error@-2{{converting 
'__attribute__((address_space(2))) char *' to type 'void *' changes address 
space of pointer}}
 }
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -6527,6 +6527,21 @@
 S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers)
 << LHSTy << RHSTy << LHS.get()->getSourceRange()
 << RHS.get()->getSourceRange();
+
+// If the addresse spacesare different, we do not allow a bitcast.
+if (!S.getLangOpts().OpenCL) {
+  if (LAddrSpace != ResultAddrSpace) {
+S.Diag(Loc, diag::err_typecheck_incompatible_address_space)
+<< LHSTy << incompatTy << Sema::AA_Converting
+<< LHS.get()->getSourceRange();
+  }
+  if (RAddrSpace != ResultAddrSpace) {
+S.Diag(Loc, diag::err_typecheck_incompatible_address_space)
+<< RHSTy << incompatTy << Sema::AA_Converting
+<< RHS.get()->getSourceRange();
+  }
+}
+
 return incompatTy;
   }
 


Index: test/Sema/conditional-expr.c
===
--- test/Sema/conditional-expr.c
+++ test/Sema/conditional-expr.c
@@ -74,9 +74,12 @@
   int __attribute__((address_space(2))) *adr2;
   int __attribute__((address_space(3))) *adr3;
   test0 ? adr2 : adr3; // expected-warning {{pointer type mismatch}} expected-warning {{expression result unused}}
+   // expected-error@-1{{converting '__attribute__((address_space(2))) int *' to type 'void *' changes address space of pointer}}
+   // expected-error@-2{{converting '__attribute__((address_space(3))) int *' to type 'void *' changes address space of pointer}}
 
   // Make sure address-space mask ends up in the result type
   (test0 ? (test0 ? adr2 : adr2) : nonconst_int); // expected-warning {{pointer type mismatch}} expected-warning {{expression result unused}}
+  // expected-error@-1{{converting '__attribute__((address_space(2))) int *' to type 'void *' changes address space of pointer}}
 }
 
 int Postgresql() {
Index: test/Sema/address_spaces.c
===
--- test/Sema/address_spaces.c
+++ test/Sema/address_spaces.c
@@ -72,4 +72,6 @@
 // Clang extension doesn't forbid operations on pointers to different address spaces.
 char* cmp(_AS1 char *x,  _AS2 char *y) {
   return x < y ? x : y; // expected-warning {{pointer type mismatch ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *')}}
+// expected-error@-1{{converting '_

[PATCH] D48661: [Fixed Point Arithmetic] Fixed Point Constant

2018-08-06 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 159320.
leonardchan marked an inline comment as done.
leonardchan added a comment.

- Fixed `Accumum` names


Repository:
  rC Clang

https://reviews.llvm.org/D48661

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/FixedPoint.h
  include/clang/Basic/TargetInfo.h
  lib/AST/ASTContext.cpp
  lib/Basic/CMakeLists.txt
  lib/Basic/FixedPoint.cpp
  lib/Sema/SemaExpr.cpp
  test/Frontend/fixed_point_declarations.c
  unittests/Basic/CMakeLists.txt
  unittests/Basic/FixedPointTest.cpp

Index: unittests/Basic/FixedPointTest.cpp
===
--- /dev/null
+++ unittests/Basic/FixedPointTest.cpp
@@ -0,0 +1,683 @@
+//===- unittests/Basic/FixedPointTest.cpp -- fixed point number tests -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "clang/Basic/FixedPoint.h"
+#include "llvm/ADT/APSInt.h"
+#include "gtest/gtest.h"
+
+using clang::APFixedPoint;
+using clang::FixedPointSemantics;
+using llvm::APInt;
+using llvm::APSInt;
+
+namespace {
+
+FixedPointSemantics Saturated(FixedPointSemantics Sema) {
+  Sema.setSaturated(true);
+  return Sema;
+}
+
+FixedPointSemantics getSAccumSema() {
+  return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/true,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getAccumSema() {
+  return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/true,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getLAccumSema() {
+  return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/true,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getSFractSema() {
+  return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/true,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getFractSema() {
+  return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/true,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getLFractSema() {
+  return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/true,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getUSAccumSema() {
+  return FixedPointSemantics(/*width=*/16, /*scale=*/8, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getUAccumSema() {
+  return FixedPointSemantics(/*width=*/32, /*scale=*/16, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getULAccumSema() {
+  return FixedPointSemantics(/*width=*/64, /*scale=*/32, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getUSFractSema() {
+  return FixedPointSemantics(/*width=*/8, /*scale=*/8, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getUFractSema() {
+  return FixedPointSemantics(/*width=*/16, /*scale=*/16, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getULFractSema() {
+  return FixedPointSemantics(/*width=*/32, /*scale=*/32, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/false);
+}
+
+FixedPointSemantics getPadUSAccumSema() {
+  return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/true);
+}
+
+FixedPointSemantics getPadUAccumSema() {
+  return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/true);
+}
+
+FixedPointSemantics getPadULAccumSema() {
+  return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/false,
+ /*isSaturated=*/false,
+ /*hasUnsignedPadding=*/true);
+}
+
+FixedPointSemantics getPadUSFractSema() {
+  return FixedPointSemanti

[PATCH] D48661: [Fixed Point Arithmetic] Fixed Point Constant

2018-08-06 Thread Leonard Chan via Phabricator via cfe-commits
This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rL339028: [Fixed Point Arithmetic] Fixed Point Constant 
(authored by leonardchan, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D48661?vs=159320&id=159321#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D48661

Files:
  cfe/trunk/include/clang/AST/ASTContext.h
  cfe/trunk/include/clang/Basic/FixedPoint.h
  cfe/trunk/include/clang/Basic/TargetInfo.h
  cfe/trunk/lib/AST/ASTContext.cpp
  cfe/trunk/lib/Basic/CMakeLists.txt
  cfe/trunk/lib/Basic/FixedPoint.cpp
  cfe/trunk/lib/Sema/SemaExpr.cpp
  cfe/trunk/test/Frontend/fixed_point_declarations.c
  cfe/trunk/unittests/Basic/CMakeLists.txt
  cfe/trunk/unittests/Basic/FixedPointTest.cpp

Index: cfe/trunk/test/Frontend/fixed_point_declarations.c
===
--- cfe/trunk/test/Frontend/fixed_point_declarations.c
+++ cfe/trunk/test/Frontend/fixed_point_declarations.c
@@ -1,5 +1,4 @@
 // RUN: %clang -ffixed-point -S -emit-llvm %s -o - --target=x86_64-linux | FileCheck %s
-// RUN: %clang -ffixed-point -S -emit-llvm %s -o - --target=x86_64-scei-ps4-ubuntu-fast | FileCheck %s
 
 // Primary fixed point types
 signed short _Accum   s_short_accum;  // CHECK-DAG: @s_short_accum  = {{.*}}global i16 0, align 2
@@ -111,3 +110,18 @@
 unsigned short _Fract u_short_fract_eps = 0x1p-8uhr;// CHECK-DAG: @u_short_fract_eps = {{.*}}global i8  1, align 1
 unsigned _Fract   u_fract_eps   = 0x1p-16ur;// CHECK-DAG: @u_fract_eps   = {{.*}}global i16 1, align 2
 unsigned long _Fract  u_long_fract_eps  = 0x1p-32ulr;   // CHECK-DAG: @u_long_fract_eps  = {{.*}}global i32 1, align 4
+
+// Zero
+short _Accum  short_accum_zero= 0.0hk;// CHECK-DAG: @short_accum_zero = {{.*}}global i16 0, align 2
+ _Accum   accum_zero  = 0.0k; // CHECK-DAG: @accum_zero   = {{.*}}global i32 0, align 4
+long _Accum   long_accum_zero = 0.0lk;// CHECK-DAG: @long_accum_zero  = {{.*}}global i64 0, align 8
+unsigned short _Accum u_short_accum_zero  = 0.0uhk;   // CHECK-DAG: @u_short_accum_zero   = {{.*}}global i16 0, align 2
+unsigned  _Accum  u_accum_zero= 0.0uk;// CHECK-DAG: @u_accum_zero = {{.*}}global i32 0, align 4
+unsigned long _Accum  u_long_accum_zero   = 0.0ulk;   // CHECK-DAG: @u_long_accum_zero= {{.*}}global i64 0, align 8
+
+short _Fract  short_fract_zero= 0.0hr;// CHECK-DAG: @short_fract_zero = {{.*}}global i8  0, align 1
+ _Fract   fract_zero  = 0.0r; // CHECK-DAG: @fract_zero   = {{.*}}global i16 0, align 2
+long _Fract   long_fract_zero = 0.0lr;// CHECK-DAG: @long_fract_zero  = {{.*}}global i32 0, align 4
+unsigned short _Fract u_short_fract_zero  = 0.0uhr;   // CHECK-DAG: @u_short_fract_zero   = {{.*}}global i8  0, align 1
+unsigned  _Fract  u_fract_zero= 0.0ur;// CHECK-DAG: @u_fract_zero = {{.*}}global i16 0, align 2
+unsigned long _Fract  u_long_fract_zero   = 0.0ulr;   // CHECK-DAG: @u_long_fract_zero= {{.*}}global i32 0, align 4
Index: cfe/trunk/lib/AST/ASTContext.cpp
===
--- cfe/trunk/lib/AST/ASTContext.cpp
+++ cfe/trunk/lib/AST/ASTContext.cpp
@@ -48,6 +48,7 @@
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/CommentOptions.h"
 #include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/FixedPoint.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/LangOptions.h"
@@ -10433,3 +10434,22 @@
   return 0;
   }
 }
+
+FixedPointSemantics ASTContext::getFixedPointSemantics(QualType Ty) const {
+  assert(Ty->isFixedPointType());
+  bool isSigned = Ty->isSignedFixedPointType();
+  return FixedPointSemantics(
+  static_cast(getTypeSize(Ty)), getFixedPointScale(Ty), isSigned,
+  Ty->isSaturatedFixedPointType(),
+  !isSigned && getTargetInfo().doUnsignedFixedPointTypesHavePadding());
+}
+
+APFixedPoint ASTContext::getFixedPointMax(QualType Ty) const {
+  assert(Ty->isFixedPointType());
+  return APFixedPoint::getMax(getFixedPointSemantics(Ty));
+}
+
+APFixedPoint ASTContext::getFixedPointMin(QualType Ty) const {
+  assert(Ty->isFixedPointType());
+  return APFixedPoint::getMin(getFixedPointSemantics(Ty));
+}
Index: cfe/trunk/lib/Sema/SemaExpr.cpp
===
--- cfe/trunk/lib/Sema/SemaExpr.cpp
+++ cfe/trunk/lib/Sema/SemaExpr.cpp
@@ -26,6 +26,7 @@
 #include "clang/AST/ExprOpenMP.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TypeLoc.h"
+#include "clang/Basic/FixedPoint.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/SourceManager.h"
 #include "cla

[PATCH] D48661: [Fixed Point Arithmetic] Fixed Point Constant

2018-08-06 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a comment.

In https://reviews.llvm.org/D48661#1189537, @bricci wrote:

> Just a nit but could you please add new-lines to your commit messages.


My bad, will remember this for future commits.

> Also the 3 bools in FixedPointSemantics are a little bit wasteful.
>  I don't know here if it matter but I have been spending the last weeks
>  cleaning up this kind of thing and this already cut the time of an 
> fsyntax-only
>  by ~3.5%.

Would you recommend something along the lines of having a bitmask instead of 3 
bools? What should I keep in mind to avoid making fsyntax-only longer?

> And using the name Sema is a bad idea IMHO since this has a totally different 
> meaning in clang.

I'll make another small patch where I rename this.


Repository:
  rL LLVM

https://reviews.llvm.org/D48661



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50278: [Sema] Fix for crash on conditional operation with address_space pointer

2018-08-06 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a comment.

In https://reviews.llvm.org/D50278#1189919, @rjmccall wrote:

> I would expect this to replace the existing warning, not to appear together 
> with it.


Will do.




Comment at: test/Sema/conditional-expr.c:78
+   // expected-error@-1{{converting 
'__attribute__((address_space(2))) int *' to type 'void *' changes address 
space of pointer}}
+   // expected-error@-2{{converting 
'__attribute__((address_space(3))) int *' to type 'void *' changes address 
space of pointer}}
 

rjmccall wrote:
> Also, these diagnostics seem wrong.  Where is `void *` coming from?
When dumping the AST this is what the resulting type is for the conditional 
expression already is if the operands are 2 pointers with different address 
spaces.

According to this comment, the reason seems to be because this is what GCC does:

```
 6512 // In this situation, we assume void* type. No especially good
 6513 // reason, but this is what gcc does, and we do have to pick
 6514 // to get a consistent AST.
```


Repository:
  rC Clang

https://reviews.llvm.org/D50278



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50278: [Sema] Fix for crash on conditional operation with address_space pointer

2018-08-06 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 159405.
leonardchan marked an inline comment as done.
leonardchan added a comment.

- Replaced instances of a `pointer type mismatch` warning involving 2 
conditional operands with different address spaces with a new error 
specifically for this situation.


Repository:
  rC Clang

https://reviews.llvm.org/D50278

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaExpr.cpp
  test/Sema/address_spaces.c
  test/Sema/conditional-expr.c


Index: test/Sema/conditional-expr.c
===
--- test/Sema/conditional-expr.c
+++ test/Sema/conditional-expr.c
@@ -73,10 +73,12 @@
 
   int __attribute__((address_space(2))) *adr2;
   int __attribute__((address_space(3))) *adr3;
-  test0 ? adr2 : adr3; // expected-warning {{pointer type mismatch}} 
expected-warning {{expression result unused}}
+  test0 ? adr2 : adr3; // expected-warning {{expression result unused}}
+   // expected-error@-1{{unable to find common type 
between '__attribute__((address_space(2))) int *' and 
'__attribute__((address_space(3))) int *' for conditional operation}}
 
   // Make sure address-space mask ends up in the result type
-  (test0 ? (test0 ? adr2 : adr2) : nonconst_int); // expected-warning 
{{pointer type mismatch}} expected-warning {{expression result unused}}
+  (test0 ? (test0 ? adr2 : adr2) : nonconst_int); // expected-warning 
{{expression result unused}}
+  // expected-error@-1{{unable 
to find common type between '__attribute__((address_space(2))) int *' and 'int 
*' for conditional operation}}
 }
 
 int Postgresql() {
Index: test/Sema/address_spaces.c
===
--- test/Sema/address_spaces.c
+++ test/Sema/address_spaces.c
@@ -71,5 +71,5 @@
 
 // Clang extension doesn't forbid operations on pointers to different address 
spaces.
 char* cmp(_AS1 char *x,  _AS2 char *y) {
-  return x < y ? x : y; // expected-warning {{pointer type mismatch 
('__attribute__((address_space(1))) char *' and 
'__attribute__((address_space(2))) char *')}}
+  return x < y ? x : y; // expected-error{{unable to find common type between 
'__attribute__((address_space(1))) char *' and 
'__attribute__((address_space(2))) char *' for conditional operation}}
 }
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -6517,16 +6517,29 @@
 S.Context.getAddrSpaceQualType(S.Context.VoidTy, ResultAddrSpace));
 LHS = S.ImpCastExprToType(LHS.get(), incompatTy, LHSCastKind);
 RHS = S.ImpCastExprToType(RHS.get(), incompatTy, RHSCastKind);
-// FIXME: For OpenCL the warning emission and cast to void* leaves a room
-// for casts between types with incompatible address space qualifiers.
-// For the following code the compiler produces casts between global and
-// local address spaces of the corresponded innermost pointees:
-// local int *global *a;
-// global int *global *b;
-// a = (0 ? a : b); // see C99 6.5.16.1.p1.
-S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers)
-<< LHSTy << RHSTy << LHS.get()->getSourceRange()
-<< RHS.get()->getSourceRange();
+
+bool HasDifferingLAddrSpace = LAddrSpace != ResultAddrSpace;
+bool HasDifferingRAddrSpace = RAddrSpace != ResultAddrSpace;
+
+if (S.getLangOpts().OpenCL ||
+!(HasDifferingLAddrSpace || HasDifferingRAddrSpace)) {
+  // FIXME: For OpenCL the warning emission and cast to void* leaves a room
+  // for casts between types with incompatible address space qualifiers.
+  // For the following code the compiler produces casts between global and
+  // local address spaces of the corresponded innermost pointees:
+  // local int *global *a;
+  // global int *global *b;
+  // a = (0 ? a : b); // see C99 6.5.16.1.p1.
+  S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers)
+  << LHSTy << RHSTy << LHS.get()->getSourceRange()
+  << RHS.get()->getSourceRange();
+} else {
+  // If the addresse spacesare different, we do not allow a bitcast.
+  S.Diag(Loc, 
diag::err_typecheck_incompatible_conditional_pointer_operands)
+  << LHSTy << RHSTy << Sema::AA_Converting
+  << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+}
+
 return incompatTy;
   }
 
Index: include/clang/Basic/DiagnosticSemaKinds.td
===
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -6939,6 +6939,8 @@
   " changes retain/release properties of pointer">;
 def err_typecheck_comparison_of_distinct_blocks : Error<
   "comparison of distinct block types%diff{ ($ and $)|}0,1">;
+def err_typecheck_incompatible_conditional_pointer_operands : Error<
+  "unable 

[PATCH] D49511: [Sema/Attribute] Check for noderef attribute

2018-08-06 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 159409.
leonardchan marked 3 inline comments as done.
leonardchan added a comment.

- Changed tick to single quote in diagnostic


Repository:
  rC Clang

https://reviews.llvm.org/D49511

Files:
  include/clang/AST/Type.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/AST/Type.cpp
  lib/AST/TypePrinter.cpp
  lib/Parse/ParseExpr.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprMember.cpp
  lib/Sema/SemaType.cpp
  test/Frontend/noderef.c
  test/Frontend/noderef_on_non_pointers.cpp
  test/Frontend/noderef_on_non_pointers.m

Index: test/Frontend/noderef_on_non_pointers.m
===
--- /dev/null
+++ test/Frontend/noderef_on_non_pointers.m
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+@interface NSObject
++ (id)new;
+@end
+
+void func() {
+  id NODEREF obj = [NSObject new]; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
Index: test/Frontend/noderef_on_non_pointers.cpp
===
--- /dev/null
+++ test/Frontend/noderef_on_non_pointers.cpp
@@ -0,0 +1,88 @@
+// RUN: %clang_cc1 -fblocks -verify %s
+
+/**
+ * Test 'noderef' attribute against other pointer-like types.
+ */
+
+#define NODEREF __attribute__((noderef))
+
+void Normal() {
+  int NODEREF i;// expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int NODEREF *i_ptr;   // ok
+  int NODEREF **i_ptr2; // ok
+  int *NODEREF i_ptr3;  // expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int *NODEREF *i_ptr4; // ok
+
+  auto NODEREF *auto_i_ptr = i_ptr;
+  auto NODEREF auto_i = i; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+
+  struct {
+int x;
+int y;
+  } NODEREF *s;
+
+  int __attribute__((noderef(10))) * no_args; // expected-error{{'noderef' attribute takes no arguments}}
+}
+
+const int NODEREF *const_i_ptr;
+static int NODEREF *static_i_ptr;
+
+void ParenTypes() {
+  int NODEREF(*i_ptr);// ok (same as `int NODEREF *`)
+  int NODEREF *(*i_ptr2); // ok (same as `int NODEREF **`)
+}
+
+// Function declarations
+int NODEREF func();   // expected-warning{{'noderef' can only be used on an array or pointer type}}
+int NODEREF *func2(); // ok (returning pointer)
+
+typedef int NODEREF (*func3)(int); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+typedef int NODEREF *(*func4)(int);
+
+void Arrays() {
+  int NODEREF i_arr[10];  // ok
+  int NODEREF i_arr2[10][10]; // ok
+  int NODEREF *i_arr3[10];// ok
+  int NODEREF i_arr4[] = {1, 2};
+}
+
+void ParenArrays() {
+  int NODEREF(i_ptr[10]);
+  int NODEREF(i_ptr2[10])[10];
+}
+
+typedef int NODEREF *(*func5[10])(int);
+
+// Arguments
+void func6(int NODEREF x); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+void func7(int NODEREF *x);
+void func8() NODEREF;
+
+void References() {
+  int x = 2;
+  int NODEREF &y = x; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int *xp = &x;
+  int NODEREF *&a = xp; // ok (reference to a NODEREF *)
+  int *NODEREF &b = xp; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+void BlockPointers() {
+  typedef int NODEREF (^IntBlock)(); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+class A {
+public:
+  int member;
+  int NODEREF *member2;
+  int NODEREF member3; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
+
+void MemberPointer() {
+  int NODEREF A::*var = &A::member; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+template 
+class B {
+  Ty NODEREF *member;
+  Ty NODEREF member2; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
Index: test/Frontend/noderef.c
===
--- /dev/null
+++ test/Frontend/noderef.c
@@ -0,0 +1,154 @@
+// RUN: %clang_cc1 -Wno-unused-value -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+struct S {
+  int a;
+  int b;
+};
+
+struct S2 {
+  int a[2];
+  int NODEREF a2[2];
+  int *b;
+  int NODEREF *b2;
+  struct S *s;
+  struct S NODEREF *s2;
+};
+
+int NODEREF *func(int NODEREF *arg) {  // expected-note{{arg declared here}}
+  int y = *arg; // expected-warning{{dereferencing arg; was declared with a 'noderef' type}}
+  return arg;
+}
+
+void func2(int x) {}
+
+int test() {
+  int NODEREF *p;   // expected-note 31 {{p declared here}}
+  int *p2;
+
+  int x = *p;   // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+  x = *((int NODEREF *)p2); // expected-warning{{dereferencing expression marked as 'noderef'}}
+
+

[PATCH] D50278: [Sema] Fix for crash on conditional operation with address_space pointer

2018-08-07 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: include/clang/Basic/DiagnosticSemaKinds.td:6943
+def err_typecheck_incompatible_conditional_pointer_operands : Error<
+  "unable to find common type between %0 and %1 for conditional operation">;
 

ebevhan wrote:
> This error is very similar to the one in my first comment, `conditional 
> operator with the second and third operands of type 
> ('__attribute__((address_space(1))) char *' and 
> '__attribute__((address_space(2))) char *') which are pointers to 
> non-overlapping address spaces`. It would normally be emitted at 6472, but 
> won't be since OpenCL isn't enabled.
Done. Removing the check for OpenCL throws this instead of the warning.



Comment at: lib/Sema/SemaExpr.cpp:6522
+bool HasDifferingLAddrSpace = LAddrSpace != ResultAddrSpace;
+bool HasDifferingRAddrSpace = RAddrSpace != ResultAddrSpace;
+

rjmccall wrote:
> I was going to tell you to use the predicate 
> `Qualifiers::isAddressSpaceSupersetOf` here, but then I was looking at the 
> uses of that, and I think the real fix is to just go into the implementation 
> of `checkConditionalPointerCompatibility` and make the compatibility logic 
> not OpenCL-specific.  The fast-path should just be whether the address spaces 
> are different.
> 
> And it looks like this function has a bug where it always uses 
> `LangAS::Default` outside of OpenCL even if the pointers are in the same 
> address space.
I'm not sure how the `LangAS::Default`, but removing all checks for OpenCL does 
the trick and prints an existing error relating to different address_spaces on 
conditional operands to replace the warning. Only 2 tests needed the change 
from the expected warning to expected error without having to change any OpenCL 
tests.

I also think the address_space comparison is already done with the 
`lhQual.isAddressSpaceSupersetOf` and `rhQual.isAddressSpaceSupersetOf`.



Comment at: test/Sema/conditional-expr.c:78
+   // expected-error@-1{{converting 
'__attribute__((address_space(2))) int *' to type 'void *' changes address 
space of pointer}}
+   // expected-error@-2{{converting 
'__attribute__((address_space(3))) int *' to type 'void *' changes address 
space of pointer}}
 

ebevhan wrote:
> rjmccall wrote:
> > leonardchan wrote:
> > > rjmccall wrote:
> > > > Also, these diagnostics seem wrong.  Where is `void *` coming from?
> > > When dumping the AST this is what the resulting type is for the 
> > > conditional expression already is if the operands are 2 pointers with 
> > > different address spaces.
> > > 
> > > According to this comment, the reason seems to be because this is what 
> > > GCC does:
> > > 
> > > ```
> > >  6512 // In this situation, we assume void* type. No especially good
> > >  6513 // reason, but this is what gcc does, and we do have to pick
> > >  6514 // to get a consistent AST.
> > > ```
> > That makes sense in general, but in this case it's not a great diagnostic; 
> > we should just emit an error when trying to pick a common type.
> Is it possible that you are getting `void *` because we aren't running the 
> qualifier removal at 6495? I don't think I've ever seen spurious `void *`'s 
> show up in our downstream diagnostics.
So the `void *` is what get's dumped for me using the latest upstream version 
of clang and is the result of the `ConditionalOperator`.

An AST dump of 

```
  3   unsigned long test0 = 5;
  4   int __attribute__((address_space(2))) *adr2;
  5   int __attribute__((address_space(3))) *adr3;
  6   test0 ? adr2 : adr3;
```

 for me returns

```
`-ConditionalOperator 0xbdbcab0  'void *'
  |-ImplicitCastExpr 0xbdbc690  'unsigned long' 
  | `-DeclRefExpr 0xbdbc618  'unsigned long' lvalue Var 0xbdbc348 
'test0' 'unsigned long'
  |-ImplicitCastExpr 0xbdbc790  'void *' 
  | `-ImplicitCastExpr 0xbdbc6a8  
'__attribute__((address_space(2))) int *' 
  |   `-DeclRefExpr 0xbdbc640  '__attribute__((address_space(2))) 
int *' lvalue Var 0xbdbc490 'adr2' '__attribute__((address_space(2))) int *'
  `-ImplicitCastExpr 0xbdbc7a8  'void *' 
`-ImplicitCastExpr 0xbdbc6c0  
'__attribute__((address_space(3))) int *' 
  `-DeclRefExpr 0xbdbc668  '__attribute__((address_space(3))) 
int *' lvalue Var 0xbdbc5a0 'adr3' '__attribute__((address_space(3))) int *'
```


Repository:
  rC Clang

https://reviews.llvm.org/D50278



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50278: [Sema] Fix for crash on conditional operation with address_space pointer

2018-08-07 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 159559.
leonardchan marked an inline comment as done.
leonardchan added a comment.

- Removed checks for OpenCL in `checkConditionalPointerCompatibility`. This 
allows for the error 
`err_typecheck_op_on_nonoverlapping_address_space_pointers` to be dumped on 
getting pointers with different address spaces instead of the warning 
`ext_typecheck_cond_incompatible_pointers`.


Repository:
  rC Clang

https://reviews.llvm.org/D50278

Files:
  lib/Sema/SemaExpr.cpp
  test/Sema/address_spaces.c
  test/Sema/conditional-expr.c

Index: test/Sema/conditional-expr.c
===
--- test/Sema/conditional-expr.c
+++ test/Sema/conditional-expr.c
@@ -73,10 +73,10 @@
 
   int __attribute__((address_space(2))) *adr2;
   int __attribute__((address_space(3))) *adr3;
-  test0 ? adr2 : adr3; // expected-warning {{pointer type mismatch}} expected-warning {{expression result unused}}
+  test0 ? adr2 : adr3; // expected-error{{conditional operator with the second and third operands of type  ('__attribute__((address_space(2))) int *' and '__attribute__((address_space(3))) int *') which are pointers to non-overlapping address spaces}}
 
   // Make sure address-space mask ends up in the result type
-  (test0 ? (test0 ? adr2 : adr2) : nonconst_int); // expected-warning {{pointer type mismatch}} expected-warning {{expression result unused}}
+  (test0 ? (test0 ? adr2 : adr2) : nonconst_int); // expected-error{{conditional operator with the second and third operands of type  ('__attribute__((address_space(2))) int *' and 'int *') which are pointers to non-overlapping address spaces}}
 }
 
 int Postgresql() {
Index: test/Sema/address_spaces.c
===
--- test/Sema/address_spaces.c
+++ test/Sema/address_spaces.c
@@ -71,5 +71,5 @@
 
 // Clang extension doesn't forbid operations on pointers to different address spaces.
 char* cmp(_AS1 char *x,  _AS2 char *y) {
-  return x < y ? x : y; // expected-warning {{pointer type mismatch ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *')}}
+  return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type  ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *') which are pointers to non-overlapping address spaces}}
 }
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -6461,20 +6461,18 @@
   LangAS ResultAddrSpace = LangAS::Default;
   LangAS LAddrSpace = lhQual.getAddressSpace();
   LangAS RAddrSpace = rhQual.getAddressSpace();
-  if (S.getLangOpts().OpenCL) {
-// OpenCL v1.1 s6.5 - Conversion between pointers to distinct address
-// spaces is disallowed.
-if (lhQual.isAddressSpaceSupersetOf(rhQual))
-  ResultAddrSpace = LAddrSpace;
-else if (rhQual.isAddressSpaceSupersetOf(lhQual))
-  ResultAddrSpace = RAddrSpace;
-else {
-  S.Diag(Loc,
- diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
-  << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange()
-  << RHS.get()->getSourceRange();
-  return QualType();
-}
+
+  // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address
+  // spaces is disallowed.
+  if (lhQual.isAddressSpaceSupersetOf(rhQual))
+ResultAddrSpace = LAddrSpace;
+  else if (rhQual.isAddressSpaceSupersetOf(lhQual))
+ResultAddrSpace = RAddrSpace;
+  else {
+S.Diag(Loc, diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
+<< LHSTy << RHSTy << 2 << LHS.get()->getSourceRange()
+<< RHS.get()->getSourceRange();
+return QualType();
   }
 
   unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers();
@@ -6492,16 +6490,12 @@
   // Thus for conditional operator we merge CVR and address space unqualified
   // pointees and if there is a composite type we return a pointer to it with
   // merged qualifiers.
-  if (S.getLangOpts().OpenCL) {
-LHSCastKind = LAddrSpace == ResultAddrSpace
-  ? CK_BitCast
-  : CK_AddressSpaceConversion;
-RHSCastKind = RAddrSpace == ResultAddrSpace
-  ? CK_BitCast
-  : CK_AddressSpaceConversion;
-lhQual.removeAddressSpace();
-rhQual.removeAddressSpace();
-  }
+  LHSCastKind =
+  LAddrSpace == ResultAddrSpace ? CK_BitCast : CK_AddressSpaceConversion;
+  RHSCastKind =
+  RAddrSpace == ResultAddrSpace ? CK_BitCast : CK_AddressSpaceConversion;
+  lhQual.removeAddressSpace();
+  rhQual.removeAddressSpace();
 
   lhptee = S.Context.getQualifiedType(lhptee.getUnqualifiedType(), lhQual);
   rhptee = S.Context.getQualifiedType(rhptee.getUnqualifiedType(), rhQual);
@@ -6517,6 +6511,7 @@
 S.Context.getAddrSpaceQualType(S.Context.VoidTy, ResultAddrSpac

[PATCH] D50278: [Sema] Fix for crash on conditional operation with address_space pointer

2018-08-07 Thread Leonard Chan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC339167: [Sema] Fix for crash on conditional operation with 
address_space pointer (authored by leonardchan, committed by ).

Repository:
  rL LLVM

https://reviews.llvm.org/D50278

Files:
  lib/Sema/SemaExpr.cpp
  test/Sema/address_spaces.c
  test/Sema/conditional-expr.c

Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -6460,20 +6460,18 @@
   LangAS ResultAddrSpace = LangAS::Default;
   LangAS LAddrSpace = lhQual.getAddressSpace();
   LangAS RAddrSpace = rhQual.getAddressSpace();
-  if (S.getLangOpts().OpenCL) {
-// OpenCL v1.1 s6.5 - Conversion between pointers to distinct address
-// spaces is disallowed.
-if (lhQual.isAddressSpaceSupersetOf(rhQual))
-  ResultAddrSpace = LAddrSpace;
-else if (rhQual.isAddressSpaceSupersetOf(lhQual))
-  ResultAddrSpace = RAddrSpace;
-else {
-  S.Diag(Loc,
- diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
-  << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange()
-  << RHS.get()->getSourceRange();
-  return QualType();
-}
+
+  // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address
+  // spaces is disallowed.
+  if (lhQual.isAddressSpaceSupersetOf(rhQual))
+ResultAddrSpace = LAddrSpace;
+  else if (rhQual.isAddressSpaceSupersetOf(lhQual))
+ResultAddrSpace = RAddrSpace;
+  else {
+S.Diag(Loc, diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
+<< LHSTy << RHSTy << 2 << LHS.get()->getSourceRange()
+<< RHS.get()->getSourceRange();
+return QualType();
   }
 
   unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers();
@@ -6491,16 +6489,12 @@
   // Thus for conditional operator we merge CVR and address space unqualified
   // pointees and if there is a composite type we return a pointer to it with
   // merged qualifiers.
-  if (S.getLangOpts().OpenCL) {
-LHSCastKind = LAddrSpace == ResultAddrSpace
-  ? CK_BitCast
-  : CK_AddressSpaceConversion;
-RHSCastKind = RAddrSpace == ResultAddrSpace
-  ? CK_BitCast
-  : CK_AddressSpaceConversion;
-lhQual.removeAddressSpace();
-rhQual.removeAddressSpace();
-  }
+  LHSCastKind =
+  LAddrSpace == ResultAddrSpace ? CK_BitCast : CK_AddressSpaceConversion;
+  RHSCastKind =
+  RAddrSpace == ResultAddrSpace ? CK_BitCast : CK_AddressSpaceConversion;
+  lhQual.removeAddressSpace();
+  rhQual.removeAddressSpace();
 
   lhptee = S.Context.getQualifiedType(lhptee.getUnqualifiedType(), lhQual);
   rhptee = S.Context.getQualifiedType(rhptee.getUnqualifiedType(), rhQual);
@@ -6516,6 +6510,7 @@
 S.Context.getAddrSpaceQualType(S.Context.VoidTy, ResultAddrSpace));
 LHS = S.ImpCastExprToType(LHS.get(), incompatTy, LHSCastKind);
 RHS = S.ImpCastExprToType(RHS.get(), incompatTy, RHSCastKind);
+
 // FIXME: For OpenCL the warning emission and cast to void* leaves a room
 // for casts between types with incompatible address space qualifiers.
 // For the following code the compiler produces casts between global and
@@ -6526,6 +6521,7 @@
 S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers)
 << LHSTy << RHSTy << LHS.get()->getSourceRange()
 << RHS.get()->getSourceRange();
+
 return incompatTy;
   }
 
Index: test/Sema/address_spaces.c
===
--- test/Sema/address_spaces.c
+++ test/Sema/address_spaces.c
@@ -71,5 +71,5 @@
 
 // Clang extension doesn't forbid operations on pointers to different address spaces.
 char* cmp(_AS1 char *x,  _AS2 char *y) {
-  return x < y ? x : y; // expected-warning {{pointer type mismatch ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *')}}
+  return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type  ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *') which are pointers to non-overlapping address spaces}}
 }
Index: test/Sema/conditional-expr.c
===
--- test/Sema/conditional-expr.c
+++ test/Sema/conditional-expr.c
@@ -73,10 +73,10 @@
 
   int __attribute__((address_space(2))) *adr2;
   int __attribute__((address_space(3))) *adr3;
-  test0 ? adr2 : adr3; // expected-warning {{pointer type mismatch}} expected-warning {{expression result unused}}
+  test0 ? adr2 : adr3; // expected-error{{conditional operator with the second and third operands of type  ('__attribute__((address_space(2))) int *' and '__attribute__((address_space(3))) int *') which are pointers to non-overlapping address spaces}}
 
   // Make sure address-space mask ends up in the result type
-  (test0 ? (test0 ? 

[PATCH] D50278: [Sema] Fix for crash on conditional operation with address_space pointer

2018-08-07 Thread Leonard Chan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL339167: [Sema] Fix for crash on conditional operation with 
address_space pointer (authored by leonardchan, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D50278?vs=159559&id=159576#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D50278

Files:
  cfe/trunk/lib/Sema/SemaExpr.cpp
  cfe/trunk/test/Sema/address_spaces.c
  cfe/trunk/test/Sema/conditional-expr.c

Index: cfe/trunk/test/Sema/conditional-expr.c
===
--- cfe/trunk/test/Sema/conditional-expr.c
+++ cfe/trunk/test/Sema/conditional-expr.c
@@ -73,10 +73,10 @@
 
   int __attribute__((address_space(2))) *adr2;
   int __attribute__((address_space(3))) *adr3;
-  test0 ? adr2 : adr3; // expected-warning {{pointer type mismatch}} expected-warning {{expression result unused}}
+  test0 ? adr2 : adr3; // expected-error{{conditional operator with the second and third operands of type  ('__attribute__((address_space(2))) int *' and '__attribute__((address_space(3))) int *') which are pointers to non-overlapping address spaces}}
 
   // Make sure address-space mask ends up in the result type
-  (test0 ? (test0 ? adr2 : adr2) : nonconst_int); // expected-warning {{pointer type mismatch}} expected-warning {{expression result unused}}
+  (test0 ? (test0 ? adr2 : adr2) : nonconst_int); // expected-error{{conditional operator with the second and third operands of type  ('__attribute__((address_space(2))) int *' and 'int *') which are pointers to non-overlapping address spaces}}
 }
 
 int Postgresql() {
Index: cfe/trunk/test/Sema/address_spaces.c
===
--- cfe/trunk/test/Sema/address_spaces.c
+++ cfe/trunk/test/Sema/address_spaces.c
@@ -71,5 +71,5 @@
 
 // Clang extension doesn't forbid operations on pointers to different address spaces.
 char* cmp(_AS1 char *x,  _AS2 char *y) {
-  return x < y ? x : y; // expected-warning {{pointer type mismatch ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *')}}
+  return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type  ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *') which are pointers to non-overlapping address spaces}}
 }
Index: cfe/trunk/lib/Sema/SemaExpr.cpp
===
--- cfe/trunk/lib/Sema/SemaExpr.cpp
+++ cfe/trunk/lib/Sema/SemaExpr.cpp
@@ -6460,20 +6460,18 @@
   LangAS ResultAddrSpace = LangAS::Default;
   LangAS LAddrSpace = lhQual.getAddressSpace();
   LangAS RAddrSpace = rhQual.getAddressSpace();
-  if (S.getLangOpts().OpenCL) {
-// OpenCL v1.1 s6.5 - Conversion between pointers to distinct address
-// spaces is disallowed.
-if (lhQual.isAddressSpaceSupersetOf(rhQual))
-  ResultAddrSpace = LAddrSpace;
-else if (rhQual.isAddressSpaceSupersetOf(lhQual))
-  ResultAddrSpace = RAddrSpace;
-else {
-  S.Diag(Loc,
- diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
-  << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange()
-  << RHS.get()->getSourceRange();
-  return QualType();
-}
+
+  // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address
+  // spaces is disallowed.
+  if (lhQual.isAddressSpaceSupersetOf(rhQual))
+ResultAddrSpace = LAddrSpace;
+  else if (rhQual.isAddressSpaceSupersetOf(lhQual))
+ResultAddrSpace = RAddrSpace;
+  else {
+S.Diag(Loc, diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
+<< LHSTy << RHSTy << 2 << LHS.get()->getSourceRange()
+<< RHS.get()->getSourceRange();
+return QualType();
   }
 
   unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers();
@@ -6491,16 +6489,12 @@
   // Thus for conditional operator we merge CVR and address space unqualified
   // pointees and if there is a composite type we return a pointer to it with
   // merged qualifiers.
-  if (S.getLangOpts().OpenCL) {
-LHSCastKind = LAddrSpace == ResultAddrSpace
-  ? CK_BitCast
-  : CK_AddressSpaceConversion;
-RHSCastKind = RAddrSpace == ResultAddrSpace
-  ? CK_BitCast
-  : CK_AddressSpaceConversion;
-lhQual.removeAddressSpace();
-rhQual.removeAddressSpace();
-  }
+  LHSCastKind =
+  LAddrSpace == ResultAddrSpace ? CK_BitCast : CK_AddressSpaceConversion;
+  RHSCastKind =
+  RAddrSpace == ResultAddrSpace ? CK_BitCast : CK_AddressSpaceConversion;
+  lhQual.removeAddressSpace();
+  rhQual.removeAddressSpace();
 
   lhptee = S.Context.getQualifiedType(lhptee.getUnqualifiedType(), lhQual);
   rhptee = S.Context.getQualifiedType(rhptee.getUnqualifiedType(), rhQual);
@@ -6516,6 +6510,7 @@
 S.Context.getAddrSpa

[PATCH] D48909: [clang-doc] Update BitcodeReader to use llvm::Error

2018-08-09 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a comment.

Should there be any tests associated with these changes?




Comment at: clang-tools-extra/clang-doc/BitcodeReader.cpp:308
-  llvm::errs() << "Invalid type for info.\n";
-  exit(1);
 }

Probably not important or it's just me being picky/dumb, but is this exit the 
intended behavior of this program when reaching this function? If so, should 
the exit also be expected even when using llvm::Error?

This also applies to the other times exit() is called in these add functions.



Comment at: clang-tools-extra/clang-doc/BitcodeReader.cpp:311
 
-template <> void addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) {
   I->Members.emplace_back(std::move(T));

Is it necessary to change the return value to llvm::Error for what were 
originally void functions?


https://reviews.llvm.org/D48909



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D43424: [clang-doc] Implement a (simple) Markdown generator

2018-08-09 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan accepted this revision.
leonardchan added inline comments.
This revision is now accepted and ready to land.



Comment at: clang-tools-extra/clang-doc/MDGenerator.cpp:79
+
+void writeHeader(const Twine &Text, int Num, raw_ostream &OS) {
+  OS << std::string(Num, '#') + " " + Text << "\n";

nit: make `Num` unsigned since the `std::string` fill ctor takes an unsigned 
value


https://reviews.llvm.org/D43424



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D49511: [Sema/Attribute] Check for noderef attribute

2018-08-09 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a comment.

@rsmith any more feedback on this current version? If it still looks incorrect 
to use the record this way, I don't mind simplifying it to work on lvalue to 
rvalue conversions without checking for a leading address space operation.


Repository:
  rC Clang

https://reviews.llvm.org/D49511



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50616: [Fixed Point Arithmetic] FixedPointCast

2018-08-12 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: ebevhan, phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.

This patch is a part of https://reviews.llvm.org/D48456 in an attempt to split 
them up. This contains the code for casting between fixed point types and other 
fixed point types.

The method for converting between fixed point types is based off the convert() 
method in APFixedPoint.


Repository:
  rC Clang

https://reviews.llvm.org/D50616

Files:
  include/clang/AST/OperationKinds.def
  include/clang/AST/Type.h
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Type.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExpr.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point_conversions.c

Index: test/Frontend/fixed_point_conversions.c
===
--- /dev/null
+++ test/Frontend/fixed_point_conversions.c
@@ -0,0 +1,326 @@
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s -check-prefix=DEFAULT
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s -check-prefix=SAME
+
+void TestFixedPointCastSameType() {
+  _Accum a = 2.5k;
+  _Accum a2 = a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+
+  a2 = (_Accum)a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+}
+
+void TestFixedPointCastDown() {
+  long _Accum la = 2.5lk;
+  _Accum a = la;
+  // DEFAULT:  [[LACCUM:%[0-9]+]] = load i64, i64* %la, align 8
+  // DEFAULT-NEXT: [[ACCUM_AS_I64:%[0-9]+]] = ashr i64 [[LACCUM]], 16
+  // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = trunc i64 [[ACCUM_AS_I64]] to i32
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+
+  a = (_Accum)la;
+  // DEFAULT:  [[LACCUM:%[0-9]+]] = load i64, i64* %la, align 8
+  // DEFAULT-NEXT: [[ACCUM_AS_I64:%[0-9]+]] = ashr i64 [[LACCUM]], 16
+  // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = trunc i64 [[ACCUM_AS_I64]] to i32
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+
+  short _Accum sa = a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: [[SACCUM_AS_I32:%[0-9]+]] = ashr i32 [[ACCUM]], 8
+  // DEFAULT-NEXT: [[SACCUM:%[0-9]+]] = trunc i32 [[SACCUM_AS_I32]] to i16
+  // DEFAULT-NEXT: store i16 [[SACCUM]], i16* %sa, align 2
+
+  sa = (short _Accum)a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: [[SACCUM_AS_I32:%[0-9]+]] = ashr i32 [[ACCUM]], 8
+  // DEFAULT-NEXT: [[SACCUM:%[0-9]+]] = trunc i32 [[SACCUM_AS_I32]] to i16
+  // DEFAULT-NEXT: store i16 [[SACCUM]], i16* %sa, align 2
+}
+
+void TestFixedPointCastUp() {
+  short _Accum sa = 2.5hk;
+  _Accum a = sa;
+  // DEFAULT:  [[SACCUM:%[0-9]+]] = load i16, i16* %sa, align 2
+  // DEFAULT-NEXT: [[SACCUM_BUFF:%[0-9]+]] = sext i16 [[SACCUM]] to i24
+  // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = shl i24 [[SACCUM_BUFF]], 8
+  // DEFAULT-NEXT: [[ACCUM_EXT:%[0-9]+]] = sext i24 [[ACCUM]] to i32
+  // DEFAULT-NEXT: store i32 [[ACCUM_EXT]], i32* %a, align 4
+
+  long _Accum la = a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: [[ACCUM_BUFF:%[0-9]+]] = sext i32 [[ACCUM]] to i48
+  // DEFAULT-NEXT: [[LACCUM:%[0-9]+]] = shl i48 [[ACCUM_BUFF]], 16
+  // DEFAULT-NEXT: [[LACCUM_EXT:%[0-9]+]] = sext i48 [[LACCUM]] to i64
+  // DEFAULT-NEXT: store i64 [[LACCUM_EXT]], i64* %la, align 8
+
+  a = (_Accum)sa;
+  // DEFAULT:  [[SACCUM:%[0-9]+]] = load i16, i16* %sa, align 2
+  // DEFAULT-NEXT: [[SACCUM_BUFF:%[0-9]+]] = sext i16 [[SACCUM]] to i24
+  // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = shl i24 [[SACCUM_BUFF]], 8
+  // DEFAULT-NEXT: [[ACCUM_EXT:%[0-9]+]] = sext i24 [[ACCUM]] to i32
+  // DEFAULT-NEXT: store i32 [[ACCUM_EXT]], i32* %a, align 4
+
+  la = (long _Accum)a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: [[ACCUM_BUFF:%[0-9]+]] = sext i32 [[ACCUM]] to i48
+  // DEFAULT-NEXT: [[LACCUM:%[0-9]+]] = shl i48 [[ACCUM_BUFF]], 16
+  // DEFAULT-NEXT: [[LACCUM_EXT:%[0-9]+]] = sext i48 [[LACCUM]] to i64
+  // DEFAULT-NEXT: store i64 [[LACCUM_EXT]], i64* %la, align 8
+}
+
+void TestFixedPointCastSignedness() {
+  _Accum a = 2.5k;
+  unsigned _Accum ua = a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: [[ACCUM_EXT:%[0-9]+]] = sext i32 [[ACCUM]] to i33
+  // DEFAULT-NEXT: [[UACCUM:%[0-9]+]] = shl i33 [[ACCUM_EXT]], 1
+  // DEFAULT-NEXT: [[ACCUM_TRUNC:%[0-9]+]] = trunc i33 [[UACCUM]] to i32
+  // DEFAULT-NEXT: store i32 [[ACCUM_TRUNC]], i32* %ua, align 4
+  // SAME:  TestFixedPointCastSignedness
+  // SAME:  [[ACCUM:%[0-9]+]] = load i32, i32* %

[PATCH] D49511: [Sema/Attribute] Check for noderef attribute

2018-08-13 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 160403.
leonardchan marked an inline comment as done.
leonardchan added a comment.

- Checks for sugared types and expressions wrapped in parenthesis


Repository:
  rC Clang

https://reviews.llvm.org/D49511

Files:
  include/clang/AST/Type.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/AST/Type.cpp
  lib/AST/TypePrinter.cpp
  lib/Parse/ParseExpr.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprMember.cpp
  lib/Sema/SemaType.cpp
  test/Frontend/noderef.c
  test/Frontend/noderef_on_non_pointers.cpp
  test/Frontend/noderef_on_non_pointers.m

Index: test/Frontend/noderef_on_non_pointers.m
===
--- /dev/null
+++ test/Frontend/noderef_on_non_pointers.m
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+@interface NSObject
++ (id)new;
+@end
+
+void func() {
+  id NODEREF obj = [NSObject new]; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
Index: test/Frontend/noderef_on_non_pointers.cpp
===
--- /dev/null
+++ test/Frontend/noderef_on_non_pointers.cpp
@@ -0,0 +1,88 @@
+// RUN: %clang_cc1 -fblocks -verify %s
+
+/**
+ * Test 'noderef' attribute against other pointer-like types.
+ */
+
+#define NODEREF __attribute__((noderef))
+
+void Normal() {
+  int NODEREF i;// expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int NODEREF *i_ptr;   // ok
+  int NODEREF **i_ptr2; // ok
+  int *NODEREF i_ptr3;  // expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int *NODEREF *i_ptr4; // ok
+
+  auto NODEREF *auto_i_ptr = i_ptr;
+  auto NODEREF auto_i = i; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+
+  struct {
+int x;
+int y;
+  } NODEREF *s;
+
+  int __attribute__((noderef(10))) * no_args; // expected-error{{'noderef' attribute takes no arguments}}
+}
+
+const int NODEREF *const_i_ptr;
+static int NODEREF *static_i_ptr;
+
+void ParenTypes() {
+  int NODEREF(*i_ptr);// ok (same as `int NODEREF *`)
+  int NODEREF *(*i_ptr2); // ok (same as `int NODEREF **`)
+}
+
+// Function declarations
+int NODEREF func();   // expected-warning{{'noderef' can only be used on an array or pointer type}}
+int NODEREF *func2(); // ok (returning pointer)
+
+typedef int NODEREF (*func3)(int); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+typedef int NODEREF *(*func4)(int);
+
+void Arrays() {
+  int NODEREF i_arr[10];  // ok
+  int NODEREF i_arr2[10][10]; // ok
+  int NODEREF *i_arr3[10];// ok
+  int NODEREF i_arr4[] = {1, 2};
+}
+
+void ParenArrays() {
+  int NODEREF(i_ptr[10]);
+  int NODEREF(i_ptr2[10])[10];
+}
+
+typedef int NODEREF *(*func5[10])(int);
+
+// Arguments
+void func6(int NODEREF x); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+void func7(int NODEREF *x);
+void func8() NODEREF;
+
+void References() {
+  int x = 2;
+  int NODEREF &y = x; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int *xp = &x;
+  int NODEREF *&a = xp; // ok (reference to a NODEREF *)
+  int *NODEREF &b = xp; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+void BlockPointers() {
+  typedef int NODEREF (^IntBlock)(); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+class A {
+public:
+  int member;
+  int NODEREF *member2;
+  int NODEREF member3; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
+
+void MemberPointer() {
+  int NODEREF A::*var = &A::member; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+template 
+class B {
+  Ty NODEREF *member;
+  Ty NODEREF member2; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
Index: test/Frontend/noderef.c
===
--- /dev/null
+++ test/Frontend/noderef.c
@@ -0,0 +1,188 @@
+// RUN: %clang_cc1 -Wno-unused-value -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+struct S {
+  int a;
+  int b;
+};
+
+struct S2 {
+  int a[2];
+  int NODEREF a2[2];
+  int *b;
+  int NODEREF *b2;
+  struct S *s;
+  struct S NODEREF *s2;
+};
+
+int NODEREF *func(int NODEREF *arg) {  // expected-note{{arg declared here}}
+  int y = *arg; // expected-warning{{dereferencing arg; was declared with a 'noderef' type}}
+  return arg;
+}
+
+void func2(int x) {}
+
+int test() {
+  int NODEREF *p; // expected-note 37 {{p declared here}}
+  int *p2;
+
+  int x = *p;   // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+  x = *((int NODEREF *)p2); // expected-warning{{dereferencing expression marked

[PATCH] D49511: [Sema/Attribute] Check for noderef attribute

2018-08-13 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a comment.

@rsmith




Comment at: lib/Sema/SemaExpr.cpp:14249
+
+if (Sema::TypeHasNoDeref(Inner))
+  DeclRef = E;

aaron.ballman wrote:
> The sugar was stripped off at the pointer level, but not at the pointee 
> level. e.g.,
> ```
> typedef int (bobble);
> typedef bobble * (frobble);
> typedef frobble * yobble;
> 
> yobble gobble;
> ```
> I think you can handle this within `TypeHasNoDeref()` and that should fix up 
> all the callers.
So `TypeHasNoDeref()` checks for the attribute on the base type already and is 
called after the pointer is stripped off. Attempting to desugar via 
`getDesugaredType()` here also removes the `address_space` attribute from the 
type I'm checking.

Do you know another method that essentially "expands" the typedefs without 
stripping the qualifiers? Otherwise I think I do need do the desugaring at the 
pointer level. Alternatively I could also change this method such that it 
accepts pointers instead of pointees since it appears I already call 
`getDesugaredType()` for almost every pointer who's pointee I'm passing to 
`TypeHasNoDeref()`.

Also I tested with your example and the warning still seems to be thrown 
appropriately. 


Repository:
  rC Clang

https://reviews.llvm.org/D49511



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D49511: [Sema/Attribute] Check for noderef attribute

2018-08-13 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 160451.
leonardchan marked 3 inline comments as done.
leonardchan added a comment.

- Remove sugar from pointee types


Repository:
  rC Clang

https://reviews.llvm.org/D49511

Files:
  include/clang/AST/Type.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/AST/Type.cpp
  lib/AST/TypePrinter.cpp
  lib/Parse/ParseExpr.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprMember.cpp
  lib/Sema/SemaType.cpp
  test/Frontend/noderef.c
  test/Frontend/noderef_on_non_pointers.cpp
  test/Frontend/noderef_on_non_pointers.m

Index: test/Frontend/noderef_on_non_pointers.m
===
--- /dev/null
+++ test/Frontend/noderef_on_non_pointers.m
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+@interface NSObject
++ (id)new;
+@end
+
+void func() {
+  id NODEREF obj = [NSObject new]; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
Index: test/Frontend/noderef_on_non_pointers.cpp
===
--- /dev/null
+++ test/Frontend/noderef_on_non_pointers.cpp
@@ -0,0 +1,88 @@
+// RUN: %clang_cc1 -fblocks -verify %s
+
+/**
+ * Test 'noderef' attribute against other pointer-like types.
+ */
+
+#define NODEREF __attribute__((noderef))
+
+void Normal() {
+  int NODEREF i;// expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int NODEREF *i_ptr;   // ok
+  int NODEREF **i_ptr2; // ok
+  int *NODEREF i_ptr3;  // expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int *NODEREF *i_ptr4; // ok
+
+  auto NODEREF *auto_i_ptr = i_ptr;
+  auto NODEREF auto_i = i; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+
+  struct {
+int x;
+int y;
+  } NODEREF *s;
+
+  int __attribute__((noderef(10))) * no_args; // expected-error{{'noderef' attribute takes no arguments}}
+}
+
+const int NODEREF *const_i_ptr;
+static int NODEREF *static_i_ptr;
+
+void ParenTypes() {
+  int NODEREF(*i_ptr);// ok (same as `int NODEREF *`)
+  int NODEREF *(*i_ptr2); // ok (same as `int NODEREF **`)
+}
+
+// Function declarations
+int NODEREF func();   // expected-warning{{'noderef' can only be used on an array or pointer type}}
+int NODEREF *func2(); // ok (returning pointer)
+
+typedef int NODEREF (*func3)(int); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+typedef int NODEREF *(*func4)(int);
+
+void Arrays() {
+  int NODEREF i_arr[10];  // ok
+  int NODEREF i_arr2[10][10]; // ok
+  int NODEREF *i_arr3[10];// ok
+  int NODEREF i_arr4[] = {1, 2};
+}
+
+void ParenArrays() {
+  int NODEREF(i_ptr[10]);
+  int NODEREF(i_ptr2[10])[10];
+}
+
+typedef int NODEREF *(*func5[10])(int);
+
+// Arguments
+void func6(int NODEREF x); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+void func7(int NODEREF *x);
+void func8() NODEREF;
+
+void References() {
+  int x = 2;
+  int NODEREF &y = x; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int *xp = &x;
+  int NODEREF *&a = xp; // ok (reference to a NODEREF *)
+  int *NODEREF &b = xp; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+void BlockPointers() {
+  typedef int NODEREF (^IntBlock)(); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+class A {
+public:
+  int member;
+  int NODEREF *member2;
+  int NODEREF member3; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
+
+void MemberPointer() {
+  int NODEREF A::*var = &A::member; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+template 
+class B {
+  Ty NODEREF *member;
+  Ty NODEREF member2; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
Index: test/Frontend/noderef.c
===
--- /dev/null
+++ test/Frontend/noderef.c
@@ -0,0 +1,205 @@
+// RUN: %clang_cc1 -Wno-unused-value -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+struct S {
+  int a;
+  int b;
+};
+
+struct S2 {
+  int a[2];
+  int NODEREF a2[2];
+  int *b;
+  int NODEREF *b2;
+  struct S *s;
+  struct S NODEREF *s2;
+};
+
+int NODEREF *func(int NODEREF *arg) {  // expected-note{{arg declared here}}
+  int y = *arg; // expected-warning{{dereferencing arg; was declared with a 'noderef' type}}
+  return arg;
+}
+
+void func2(int x) {}
+
+int test() {
+  int NODEREF *p; // expected-note 37 {{p declared here}}
+  int *p2;
+
+  int x = *p;   // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+  x = *((int NODEREF *)p2); // expected-warning{{dereferencing expression marked as 'noderef'}}
+
+  int NODEREF

[PATCH] D49511: [Sema/Attribute] Check for noderef attribute

2018-08-13 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: lib/Sema/SemaExpr.cpp:14249
+
+if (Sema::TypeHasNoDeref(Inner))
+  DeclRef = E;

aaron.ballman wrote:
> leonardchan wrote:
> > aaron.ballman wrote:
> > > The sugar was stripped off at the pointer level, but not at the pointee 
> > > level. e.g.,
> > > ```
> > > typedef int (bobble);
> > > typedef bobble * (frobble);
> > > typedef frobble * yobble;
> > > 
> > > yobble gobble;
> > > ```
> > > I think you can handle this within `TypeHasNoDeref()` and that should fix 
> > > up all the callers.
> > So `TypeHasNoDeref()` checks for the attribute on the base type already and 
> > is called after the pointer is stripped off. Attempting to desugar via 
> > `getDesugaredType()` here also removes the `address_space` attribute from 
> > the type I'm checking.
> > 
> > Do you know another method that essentially "expands" the typedefs without 
> > stripping the qualifiers? Otherwise I think I do need do the desugaring at 
> > the pointer level. Alternatively I could also change this method such that 
> > it accepts pointers instead of pointees since it appears I already call 
> > `getDesugaredType()` for almost every pointer who's pointee I'm passing to 
> > `TypeHasNoDeref()`.
> > 
> > Also I tested with your example and the warning still seems to be thrown 
> > appropriately. 
> I think you have to do the desugaring manually in a loop with 
> `getSingleStepDesugaredType()` so that you don't strip off attributed type 
> information along with the rest of the type sugar.
> 
> > Also I tested with your example and the warning still seems to be thrown 
> > appropriately.
> 
> The example may depend on where you put the attribute (inside the parens vs 
> outside the parens, for instance); it was an off-the-cuff example, so it may 
> need some tweaking.
Done. Also added different variations of your example to the tests.


Repository:
  rC Clang

https://reviews.llvm.org/D49511



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50616: [Fixed Point Arithmetic] FixedPointCast

2018-08-15 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 160884.
leonardchan marked 3 inline comments as done.
leonardchan added a comment.

- Added check for if we should check for saturation when converting to a 
saturated fixed point type.
- Replaced `llvm_unreachable()`s with temporary diagnostic to be eventually 
replaced when the conversions get implemented.


Repository:
  rC Clang

https://reviews.llvm.org/D50616

Files:
  include/clang/AST/OperationKinds.def
  include/clang/AST/Type.h
  include/clang/Basic/DiagnosticCommonKinds.td
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Type.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExpr.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point_conversions.c
  test/Frontend/fixed_point_unknown_conversions.c

Index: test/Frontend/fixed_point_unknown_conversions.c
===
--- /dev/null
+++ test/Frontend/fixed_point_unknown_conversions.c
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -verify -ffixed-point %s
+
+void func() {
+  _Bool b;
+  char c;
+  int i;
+  float f;
+  double d;
+  double _Complex dc;
+  int _Complex ic;
+  struct S {
+int i;
+  } s;
+  enum E {
+A
+  } e;
+  int *ptr;
+  typedef int int_t;
+  int_t i2;
+
+  _Accum accum;
+  _Fract fract = accum; // ok
+  _Accum *accum_ptr;
+
+  accum = b;   // expected-error{{conversion between fixed point and '_Bool' is not yet supported}}
+  accum = i;   // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+  accum = i;   // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+  accum = f;   // expected-error{{conversion between fixed point and 'float' is not yet supported}}
+  accum = d;   // expected-error{{conversion between fixed point and 'double' is not yet supported}}
+  accum = dc;  // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}}
+  accum = ic;  // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}}
+  accum = s;   // expected-error{{assigning to '_Accum' from incompatible type 'struct S'}}
+  accum = e;   // expected-error{{conversion between fixed point and 'enum E' is not yet supported}}
+  accum = ptr; // expected-error{{assigning to '_Accum' from incompatible type 'int *'}}
+  accum_ptr = ptr; // expected-warning{{incompatible pointer types assigning to '_Accum *' from 'int *'}}
+  accum = i2;  // expected-error{{conversion between fixed point and 'int_t' (aka 'int') is not yet supported}}
+
+  b = accum;   // expected-error{{conversion between fixed point and '_Bool' is not yet supported}}
+  c = accum;   // expected-error{{conversion between fixed point and 'char' is not yet supported}}
+  i = accum;   // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+  f = accum;   // expected-error{{conversion between fixed point and 'float' is not yet supported}}
+  d = accum;   // expected-error{{conversion between fixed point and 'double' is not yet supported}}
+  dc = accum;  // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}}
+  ic = accum;  // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}}
+  s = accum;   // expected-error{{assigning to 'struct S' from incompatible type '_Accum'}}
+  e = accum;   // expected-error{{conversion between fixed point and 'enum E' is not yet supported}}
+  ptr = accum; // expected-error{{assigning to 'int *' from incompatible type '_Accum'}}
+  ptr = accum_ptr; // expected-warning{{incompatible pointer types assigning to 'int *' from '_Accum *'}}
+  i2 = accum;  // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+}
Index: test/Frontend/fixed_point_conversions.c
===
--- /dev/null
+++ test/Frontend/fixed_point_conversions.c
@@ -0,0 +1,326 @@
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s -check-prefix=DEFAULT
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s -check-prefix=SAME
+
+void TestFixedPointCastSameType() {
+  _Accum a = 2.5k;
+  _Accum a2 = a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+
+  a2 = (_Accum)a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+}
+
+void TestFixedPointCastDown() {
+  long _Accum la = 2.5lk;
+  _Accum a = la;
+  // DEFAULT:  [[LACCUM:%[0-9]+]] = load i64, i64* %la, align 8
+  // DEFAULT-NEXT: [[ACCUM_AS_I64:%[0-9]

[PATCH] D50616: [Fixed Point Arithmetic] FixedPointCast

2018-08-15 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: lib/CodeGen/CGExprScalar.cpp:1016
+  if (DstScale > SrcScale) {
+// Need to allocate space before shifting left
+ResultWidth = SrcWidth + DstScale - SrcScale;

rjmccall wrote:
> In IR, this isn't really "allocating" space.
My bad. Poor comment wording.



Comment at: lib/CodeGen/CGExprScalar.cpp:1034
+  if (DstFPSema.isSaturated() &&
+  (CGF.getContext().getCorrespondingSaturatedType(SrcTy) != DstTy)) {
+auto Mask = APInt::getBitsSetFrom(

rjmccall wrote:
> Why is this condition based on the formal types exactly matching rather than 
> something about the FP semantics being different?  Formal types can 
> correspond to the same format, right?
> 
> We need to check for saturation if we're either (1) decreasing the magnitude 
> of the highest usable bit or (2) going signed->unsigned, (2) we're going 
> signed->unsigned, or (3) we're going unsigned->signed without increasing the 
> number of integral bits.  And I'd expect the checks we have to do in each 
> case to be different.
For simplicity, I more or less copied the logic from `APFixedPoint::convert()` 
which performs a saturation check that covers all of these cases if the 
destination semantics were saturated.

Added another condition that checks if we need to perform saturation checks. I 
think your (1) and (3) might be the same thing since I think we only really 
need to check if the magnitude decreases or if going from signed -> unsigned. 

I think though that the IR emission would be the same since both cases will 
require checking for a change in the magnitude (via the mask). The only 
difference is that if going from signed->unsigned, the min saturation is zero 
if the value is negative.



Comment at: lib/Sema/SemaExpr.cpp:5889
+case Type::STK_MemberPointer:
+  llvm_unreachable("Unimplemented conversion from FixedPoint to type");
+}

rjmccall wrote:
> Is there something I'm missing that actually diagnoses the unimplemented 
> cases here?  There's a lot of code that seems to assume that any two 
> arithmetic types can be converted to each other, and we do prefer not to 
> crash the compiler, especially on valid code.
The plan was to implement these in other patches. I wasn't sure if 
`llvm_unreachable()` was ok to use as a placeholder for features that will 
eventually be implemented.

Added diagnostics here for now to be eventually removed once these casts are 
implemented in later patches.


Repository:
  rC Clang

https://reviews.llvm.org/D50616



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D49511: [Sema/Attribute] Check for noderef attribute

2018-08-15 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 160892.
leonardchan marked 6 inline comments as done.

Repository:
  rC Clang

https://reviews.llvm.org/D49511

Files:
  include/clang/AST/Type.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/AST/Type.cpp
  lib/AST/TypePrinter.cpp
  lib/Parse/ParseExpr.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprMember.cpp
  lib/Sema/SemaType.cpp
  test/Frontend/noderef.c
  test/Frontend/noderef_on_non_pointers.cpp
  test/Frontend/noderef_on_non_pointers.m

Index: test/Frontend/noderef_on_non_pointers.m
===
--- /dev/null
+++ test/Frontend/noderef_on_non_pointers.m
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+@interface NSObject
++ (id)new;
+@end
+
+void func() {
+  id NODEREF obj = [NSObject new]; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
Index: test/Frontend/noderef_on_non_pointers.cpp
===
--- /dev/null
+++ test/Frontend/noderef_on_non_pointers.cpp
@@ -0,0 +1,88 @@
+// RUN: %clang_cc1 -fblocks -verify %s
+
+/**
+ * Test 'noderef' attribute against other pointer-like types.
+ */
+
+#define NODEREF __attribute__((noderef))
+
+void Normal() {
+  int NODEREF i;// expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int NODEREF *i_ptr;   // ok
+  int NODEREF **i_ptr2; // ok
+  int *NODEREF i_ptr3;  // expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int *NODEREF *i_ptr4; // ok
+
+  auto NODEREF *auto_i_ptr = i_ptr;
+  auto NODEREF auto_i = i; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+
+  struct {
+int x;
+int y;
+  } NODEREF *s;
+
+  int __attribute__((noderef(10))) * no_args; // expected-error{{'noderef' attribute takes no arguments}}
+}
+
+const int NODEREF *const_i_ptr;
+static int NODEREF *static_i_ptr;
+
+void ParenTypes() {
+  int NODEREF(*i_ptr);// ok (same as `int NODEREF *`)
+  int NODEREF *(*i_ptr2); // ok (same as `int NODEREF **`)
+}
+
+// Function declarations
+int NODEREF func();   // expected-warning{{'noderef' can only be used on an array or pointer type}}
+int NODEREF *func2(); // ok (returning pointer)
+
+typedef int NODEREF (*func3)(int); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+typedef int NODEREF *(*func4)(int);
+
+void Arrays() {
+  int NODEREF i_arr[10];  // ok
+  int NODEREF i_arr2[10][10]; // ok
+  int NODEREF *i_arr3[10];// ok
+  int NODEREF i_arr4[] = {1, 2};
+}
+
+void ParenArrays() {
+  int NODEREF(i_ptr[10]);
+  int NODEREF(i_ptr2[10])[10];
+}
+
+typedef int NODEREF *(*func5[10])(int);
+
+// Arguments
+void func6(int NODEREF x); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+void func7(int NODEREF *x);
+void func8() NODEREF;
+
+void References() {
+  int x = 2;
+  int NODEREF &y = x; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int *xp = &x;
+  int NODEREF *&a = xp; // ok (reference to a NODEREF *)
+  int *NODEREF &b = xp; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+void BlockPointers() {
+  typedef int NODEREF (^IntBlock)(); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+class A {
+public:
+  int member;
+  int NODEREF *member2;
+  int NODEREF member3; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
+
+void MemberPointer() {
+  int NODEREF A::*var = &A::member; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+template 
+class B {
+  Ty NODEREF *member;
+  Ty NODEREF member2; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
Index: test/Frontend/noderef.c
===
--- /dev/null
+++ test/Frontend/noderef.c
@@ -0,0 +1,205 @@
+// RUN: %clang_cc1 -Wno-unused-value -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+struct S {
+  int a;
+  int b;
+};
+
+struct S2 {
+  int a[2];
+  int NODEREF a2[2];
+  int *b;
+  int NODEREF *b2;
+  struct S *s;
+  struct S NODEREF *s2;
+};
+
+int NODEREF *func(int NODEREF *arg) {  // expected-note{{arg declared here}}
+  int y = *arg; // expected-warning{{dereferencing arg; was declared with a 'noderef' type}}
+  return arg;
+}
+
+void func2(int x) {}
+
+int test() {
+  int NODEREF *p; // expected-note 37 {{p declared here}}
+  int *p2;
+
+  int x = *p;   // expected-warning{{dereferencing p; was declared with a 'noderef' type}}
+  x = *((int NODEREF *)p2); // expected-warning{{dereferencing expression marked as 'noderef'}}
+
+  int NODEREF **q;
+  int *NODEREF *q2; // expected-note 4 {{q2 declared here}

[PATCH] D50616: [Fixed Point Arithmetic] FixedPointCast

2018-08-15 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 160964.
leonardchan marked 7 inline comments as done.
leonardchan added a comment.

- Reworked logic for saturation


Repository:
  rC Clang

https://reviews.llvm.org/D50616

Files:
  include/clang/AST/OperationKinds.def
  include/clang/AST/Type.h
  include/clang/Basic/DiagnosticCommonKinds.td
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Type.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExpr.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point_conversions.c
  test/Frontend/fixed_point_unknown_conversions.c

Index: test/Frontend/fixed_point_unknown_conversions.c
===
--- /dev/null
+++ test/Frontend/fixed_point_unknown_conversions.c
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -verify -ffixed-point %s
+
+void func() {
+  _Bool b;
+  char c;
+  int i;
+  float f;
+  double d;
+  double _Complex dc;
+  int _Complex ic;
+  struct S {
+int i;
+  } s;
+  enum E {
+A
+  } e;
+  int *ptr;
+  typedef int int_t;
+  int_t i2;
+
+  _Accum accum;
+  _Fract fract = accum; // ok
+  _Accum *accum_ptr;
+
+  accum = b;   // expected-error{{conversion between fixed point and '_Bool' is not yet supported}}
+  accum = i;   // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+  accum = i;   // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+  accum = f;   // expected-error{{conversion between fixed point and 'float' is not yet supported}}
+  accum = d;   // expected-error{{conversion between fixed point and 'double' is not yet supported}}
+  accum = dc;  // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}}
+  accum = ic;  // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}}
+  accum = s;   // expected-error{{assigning to '_Accum' from incompatible type 'struct S'}}
+  accum = e;   // expected-error{{conversion between fixed point and 'enum E' is not yet supported}}
+  accum = ptr; // expected-error{{assigning to '_Accum' from incompatible type 'int *'}}
+  accum_ptr = ptr; // expected-warning{{incompatible pointer types assigning to '_Accum *' from 'int *'}}
+  accum = i2;  // expected-error{{conversion between fixed point and 'int_t' (aka 'int') is not yet supported}}
+
+  b = accum;   // expected-error{{conversion between fixed point and '_Bool' is not yet supported}}
+  c = accum;   // expected-error{{conversion between fixed point and 'char' is not yet supported}}
+  i = accum;   // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+  f = accum;   // expected-error{{conversion between fixed point and 'float' is not yet supported}}
+  d = accum;   // expected-error{{conversion between fixed point and 'double' is not yet supported}}
+  dc = accum;  // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}}
+  ic = accum;  // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}}
+  s = accum;   // expected-error{{assigning to 'struct S' from incompatible type '_Accum'}}
+  e = accum;   // expected-error{{conversion between fixed point and 'enum E' is not yet supported}}
+  ptr = accum; // expected-error{{assigning to 'int *' from incompatible type '_Accum'}}
+  ptr = accum_ptr; // expected-warning{{incompatible pointer types assigning to 'int *' from '_Accum *'}}
+  i2 = accum;  // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+}
Index: test/Frontend/fixed_point_conversions.c
===
--- /dev/null
+++ test/Frontend/fixed_point_conversions.c
@@ -0,0 +1,294 @@
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s -check-prefix=DEFAULT
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s -check-prefix=SAME
+
+void TestFixedPointCastSameType() {
+  _Accum a = 2.5k;
+  _Accum a2 = a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+
+  a2 = (_Accum)a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+}
+
+void TestFixedPointCastDown() {
+  long _Accum la = 2.5lk;
+  _Accum a = la;
+  // DEFAULT:  [[LACCUM:%[0-9]+]] = load i64, i64* %la, align 8
+  // DEFAULT-NEXT: [[ACCUM_AS_I64:%[0-9]+]] = ashr i64 [[LACCUM]], 16
+  // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = trunc i64 [[ACCUM_AS_I64]] to i32
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+
+  a = (_Accum)la;
+  // DEFAU

[PATCH] D50616: [Fixed Point Arithmetic] FixedPointCast

2018-08-15 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: lib/CodeGen/CGExprScalar.cpp:1034
+  if (DstFPSema.isSaturated() &&
+  (CGF.getContext().getCorrespondingSaturatedType(SrcTy) != DstTy)) {
+auto Mask = APInt::getBitsSetFrom(

rjmccall wrote:
> leonardchan wrote:
> > rjmccall wrote:
> > > Why is this condition based on the formal types exactly matching rather 
> > > than something about the FP semantics being different?  Formal types can 
> > > correspond to the same format, right?
> > > 
> > > We need to check for saturation if we're either (1) decreasing the 
> > > magnitude of the highest usable bit or (2) going signed->unsigned, (2) 
> > > we're going signed->unsigned, or (3) we're going unsigned->signed without 
> > > increasing the number of integral bits.  And I'd expect the checks we 
> > > have to do in each case to be different.
> > For simplicity, I more or less copied the logic from 
> > `APFixedPoint::convert()` which performs a saturation check that covers all 
> > of these cases if the destination semantics were saturated.
> > 
> > Added another condition that checks if we need to perform saturation 
> > checks. I think your (1) and (3) might be the same thing since I think we 
> > only really need to check if the magnitude decreases or if going from 
> > signed -> unsigned. 
> > 
> > I think though that the IR emission would be the same since both cases will 
> > require checking for a change in the magnitude (via the mask). The only 
> > difference is that if going from signed->unsigned, the min saturation is 
> > zero if the value is negative.
> Wow, sorry for the edit failure in that review comment.  You're right, it 
> should've been just (1) and the first (2).
> 
> Are there no fixed-point formats for which the range doesn't go up to 
> (almost) 1?  I guess there probably aren't.
No problem. The smallest range that a fixed point type can cover is the 
`_Fract` type which covers [-1, 1).



Comment at: lib/CodeGen/CGExprScalar.cpp:1044
+
+Value *IsNegative = nullptr;
+if (Mask != 0) {

rjmccall wrote:
> I'm sorry, but this code is really impenetrable.  The variable names are 
> non-descriptive, and there are a lot of uncommented dependencies between 
> values, like how `IsNegative` propagates out, and like how it's checking 
> without explanation that there's not a magnitude change using whether the 
> mask ends up being all-zero.  Please just assign the two components of 
> `ShouldCheckSaturation` to reasonably-named local variables and then use 
> those to guide the code-generation here.
> 
> Also, the code being generated here is pretty weird.  I'm not sure the mask 
> is helping; it might both produce better code and be easier to understand if 
> you just broke it down into cases, like this:
> 
> ```
>   if a magnitude check is required {
> auto Max = maximum value of dest type;
> auto TooHigh = IsSigned ? Builder.CreateICmpSGT(Result, Max) : 
> Builder.CreateICmpUGT(Result, Max);
> Result = Builder.CreateSelect(TooHigh, Max, Result);
>   }
> 
>   if signed -> unsigned {
> auto Zero = zero value of dest type;
> Result = Builder.CreateSelect(Builder.CreateICmpSLT(Result, Zero), Zero, 
> Result);
>   } else if (IsSigned) {
> auto Min = minimum value of dest type;
> Result = Builder.CreateSelect(Builder.CreateICmpSLT(Result, Min), Min, 
> Result);
>   }
> ```
My bad. I guess it seemed intuitive at first but can see how it's difficult to 
read.

This is the full logic and reasoning for the mask: 
https://reviews.llvm.org/D48661?id=153426#inline-427647

But to summarize, it's essentially for checking if the bits above the MSB 
changed which would indicate saturation needs to occur.
- `Mask` is for getting the bits above the integral bits in the resulting type 
(for signed types, this also captures the sign bit)
- `Masked` is the bits above the highest integral bit in the resulting type
- `Masked == Mask` indicates that all the bits above the highest integral bit 
were ones (the value is negative) and none of them changed (no change in 
magnitude)
- `Mask == 0` indicates that all the bits above the highest integral bit were 
zeros (the value is non-negative) and none of them changed (no  change in 
magnitude)
- `Masked == Mask || Mask == 0` therefore indicates no change in magnitude
- `!(Masked == Mask || Mask == 0)` indicates a change in magnitude and we 
should saturate (but to save an extra instruction, this was emitted as `Masked 
!= Mask && Mask != 0`
- If we saturate, `Mask` also happens to be the min value we saturate to for 
signed types and `~Mask` is also the max value we saturate to.

The reason for the `IsNegative` laid out like that is to prevent from emitting 
an extra instruction for checking a negative value.


Repository:
  rC Clang

https://reviews.llvm.org/D50616



___
cfe-commits mailing list
cfe-commits@lists.llvm.org

[PATCH] D50616: [Fixed Point Arithmetic] FixedPointCast

2018-08-16 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 161087.
leonardchan marked 6 inline comments as done.
leonardchan added a comment.

- Added separate case for conversions to a non-saturated type


Repository:
  rC Clang

https://reviews.llvm.org/D50616

Files:
  include/clang/AST/OperationKinds.def
  include/clang/AST/Type.h
  include/clang/Basic/DiagnosticCommonKinds.td
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Type.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExpr.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point_conversions.c
  test/Frontend/fixed_point_unknown_conversions.c

Index: test/Frontend/fixed_point_unknown_conversions.c
===
--- /dev/null
+++ test/Frontend/fixed_point_unknown_conversions.c
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -verify -ffixed-point %s
+
+void func() {
+  _Bool b;
+  char c;
+  int i;
+  float f;
+  double d;
+  double _Complex dc;
+  int _Complex ic;
+  struct S {
+int i;
+  } s;
+  enum E {
+A
+  } e;
+  int *ptr;
+  typedef int int_t;
+  int_t i2;
+
+  _Accum accum;
+  _Fract fract = accum; // ok
+  _Accum *accum_ptr;
+
+  accum = b;   // expected-error{{conversion between fixed point and '_Bool' is not yet supported}}
+  accum = i;   // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+  accum = i;   // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+  accum = f;   // expected-error{{conversion between fixed point and 'float' is not yet supported}}
+  accum = d;   // expected-error{{conversion between fixed point and 'double' is not yet supported}}
+  accum = dc;  // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}}
+  accum = ic;  // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}}
+  accum = s;   // expected-error{{assigning to '_Accum' from incompatible type 'struct S'}}
+  accum = e;   // expected-error{{conversion between fixed point and 'enum E' is not yet supported}}
+  accum = ptr; // expected-error{{assigning to '_Accum' from incompatible type 'int *'}}
+  accum_ptr = ptr; // expected-warning{{incompatible pointer types assigning to '_Accum *' from 'int *'}}
+  accum = i2;  // expected-error{{conversion between fixed point and 'int_t' (aka 'int') is not yet supported}}
+
+  b = accum;   // expected-error{{conversion between fixed point and '_Bool' is not yet supported}}
+  c = accum;   // expected-error{{conversion between fixed point and 'char' is not yet supported}}
+  i = accum;   // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+  f = accum;   // expected-error{{conversion between fixed point and 'float' is not yet supported}}
+  d = accum;   // expected-error{{conversion between fixed point and 'double' is not yet supported}}
+  dc = accum;  // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}}
+  ic = accum;  // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}}
+  s = accum;   // expected-error{{assigning to 'struct S' from incompatible type '_Accum'}}
+  e = accum;   // expected-error{{conversion between fixed point and 'enum E' is not yet supported}}
+  ptr = accum; // expected-error{{assigning to 'int *' from incompatible type '_Accum'}}
+  ptr = accum_ptr; // expected-warning{{incompatible pointer types assigning to 'int *' from '_Accum *'}}
+  i2 = accum;  // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+}
Index: test/Frontend/fixed_point_conversions.c
===
--- /dev/null
+++ test/Frontend/fixed_point_conversions.c
@@ -0,0 +1,283 @@
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s -check-prefix=DEFAULT
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s -check-prefix=SAME
+
+void TestFixedPointCastSameType() {
+  _Accum a = 2.5k;
+  _Accum a2 = a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+
+  a2 = (_Accum)a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+}
+
+void TestFixedPointCastDown() {
+  long _Accum la = 2.5lk;
+  _Accum a = la;
+  // DEFAULT:  [[LACCUM:%[0-9]+]] = load i64, i64* %la, align 8
+  // DEFAULT-NEXT: [[ACCUM_AS_I64:%[0-9]+]] = ashr i64 [[LACCUM]], 16
+  // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = trunc i64 [[ACCUM_AS_I64]] to i32
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+

[PATCH] D50616: [Fixed Point Arithmetic] FixedPointCast

2018-08-16 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: lib/CodeGen/CGExprScalar.cpp:331
+  SourceLocation Loc);
+
   /// Emit a conversion from the specified complex type to the specified

ebevhan wrote:
> What's the plan for the other conversions (int<->fix, float<->fix)? Functions 
> for those as well?
> 
> What about `EmitScalarConversion`? If it cannot handle conversions of 
> fixed-point values it should probably be made to assert, since it will likely 
> mess up.
Ideally, my plan was to have separate functions for each cast since it seems 
the logic for each of them is unique, other than saturation which may be 
abstracted to its own function and be used by the others.

I wasn't sure if I should also place the logic for these casts in 
`EmitScalarConversion` since `EmitScalarConversion` seemed pretty large enough 
and thought it was easier if we instead had separate, self contained functions 
for each fixed point conversion. But I'm open for hearing ideas on different 
ways on implementing them.

Will add the assertion.



Comment at: lib/CodeGen/CGExprScalar.cpp:1052
+} else if (IsSigned && !DstFPSema.isSigned()) {
+  Value *Zero =
+  ConstantInt::get(CGF.getLLVMContext(), APInt(ResultWidth, 0));

ebevhan wrote:
> `ConstantInt::getNullValue`?
I did not know about this method. Thanks!



Comment at: lib/Sema/Sema.cpp:537
+  case Type::STK_FixedPoint:
+llvm_unreachable("Unknown cast from FixedPoint to boolean");
   }

ebevhan wrote:
> Will we want to support this?
I imagine we would want `_Bool` conversions since logical negation works on 
fixed point types and more people would probably assume by default for it to 
also implicitly be converted to a boolean as opposed to not.

I also don't think implementing in a later patch this will be too hard.


Repository:
  rC Clang

https://reviews.llvm.org/D50616



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50616: [Fixed Point Arithmetic] FixedPointCast

2018-08-16 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a comment.

In https://reviews.llvm.org/D50616#1202034, @ebevhan wrote:

> I think I've mentioned this before, but I would like to discuss the 
> possibility of adding a target hook(s) for some of these operations 
> (conversions, arithmetic when it comes). Precisely matching the emitted 
> saturation operation is virtually impossible for a target.


Sorry I forgot to address this also. Just to make sure I understand this 
correctly since I haven't used these before: target hooks are essentially for 
emitting target specific code for some operations right? Does this mean that 
the `EmitFixedPointConversion` function should be moved to a virtual method 
under `TargetCodeGenInfo` that can be overridden and this is what get's called 
instead during conversion?


Repository:
  rC Clang

https://reviews.llvm.org/D50616



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50616: [Fixed Point Arithmetic] FixedPointCast

2018-08-17 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 161298.
leonardchan marked 4 inline comments as done.

Repository:
  rC Clang

https://reviews.llvm.org/D50616

Files:
  include/clang/AST/OperationKinds.def
  include/clang/AST/Type.h
  include/clang/Basic/DiagnosticCommonKinds.td
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Type.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/CodeGen/TargetInfo.cpp
  lib/CodeGen/TargetInfo.h
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExpr.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point_conversions.c
  test/Frontend/fixed_point_unknown_conversions.c

Index: test/Frontend/fixed_point_unknown_conversions.c
===
--- /dev/null
+++ test/Frontend/fixed_point_unknown_conversions.c
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -verify -ffixed-point %s
+
+void func() {
+  _Bool b;
+  char c;
+  int i;
+  float f;
+  double d;
+  double _Complex dc;
+  int _Complex ic;
+  struct S {
+int i;
+  } s;
+  enum E {
+A
+  } e;
+  int *ptr;
+  typedef int int_t;
+  int_t i2;
+
+  _Accum accum;
+  _Fract fract = accum; // ok
+  _Accum *accum_ptr;
+
+  accum = b;   // expected-error{{conversion between fixed point and '_Bool' is not yet supported}}
+  accum = i;   // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+  accum = i;   // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+  accum = f;   // expected-error{{conversion between fixed point and 'float' is not yet supported}}
+  accum = d;   // expected-error{{conversion between fixed point and 'double' is not yet supported}}
+  accum = dc;  // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}}
+  accum = ic;  // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}}
+  accum = s;   // expected-error{{assigning to '_Accum' from incompatible type 'struct S'}}
+  accum = e;   // expected-error{{conversion between fixed point and 'enum E' is not yet supported}}
+  accum = ptr; // expected-error{{assigning to '_Accum' from incompatible type 'int *'}}
+  accum_ptr = ptr; // expected-warning{{incompatible pointer types assigning to '_Accum *' from 'int *'}}
+  accum = i2;  // expected-error{{conversion between fixed point and 'int_t' (aka 'int') is not yet supported}}
+
+  b = accum;   // expected-error{{conversion between fixed point and '_Bool' is not yet supported}}
+  c = accum;   // expected-error{{conversion between fixed point and 'char' is not yet supported}}
+  i = accum;   // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+  f = accum;   // expected-error{{conversion between fixed point and 'float' is not yet supported}}
+  d = accum;   // expected-error{{conversion between fixed point and 'double' is not yet supported}}
+  dc = accum;  // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}}
+  ic = accum;  // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}}
+  s = accum;   // expected-error{{assigning to 'struct S' from incompatible type '_Accum'}}
+  e = accum;   // expected-error{{conversion between fixed point and 'enum E' is not yet supported}}
+  ptr = accum; // expected-error{{assigning to 'int *' from incompatible type '_Accum'}}
+  ptr = accum_ptr; // expected-warning{{incompatible pointer types assigning to 'int *' from '_Accum *'}}
+  i2 = accum;  // expected-error{{conversion between fixed point and 'int' is not yet supported}}
+}
Index: test/Frontend/fixed_point_conversions.c
===
--- /dev/null
+++ test/Frontend/fixed_point_conversions.c
@@ -0,0 +1,283 @@
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s -check-prefix=DEFAULT
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s -check-prefix=SAME
+
+void TestFixedPointCastSameType() {
+  _Accum a = 2.5k;
+  _Accum a2 = a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+
+  a2 = (_Accum)a;
+  // DEFAULT:  [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+}
+
+void TestFixedPointCastDown() {
+  long _Accum la = 2.5lk;
+  _Accum a = la;
+  // DEFAULT:  [[LACCUM:%[0-9]+]] = load i64, i64* %la, align 8
+  // DEFAULT-NEXT: [[ACCUM_AS_I64:%[0-9]+]] = ashr i64 [[LACCUM]], 16
+  // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = trunc i64 [[ACCUM_AS_I64]] to i32
+  // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+
+  a = (_Accum)la;
+  // DEFAULT:

[PATCH] D50616: [Fixed Point Arithmetic] FixedPointCast

2018-08-17 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a comment.

In https://reviews.llvm.org/D50616#1203692, @ebevhan wrote:

> In https://reviews.llvm.org/D50616#1203446, @leonardchan wrote:
>
> > Sorry I forgot to address this also. Just to make sure I understand this 
> > correctly since I haven't used these before: target hooks are essentially 
> > for emitting target specific code for some operations right? Does this mean 
> > that the `EmitFixedPointConversion` function should be moved to a virtual 
> > method under `TargetCodeGenInfo` that can be overridden and this is what 
> > get's called instead during conversion?
>
>
> Yes, the thought I had was to have a virtual function in TargetCodeGenInfo 
> that would be called first thing in EmitFixedPointConversion, and if it 
> returns non-null it uses that value instead. It's a bit unfortunate in this 
> instance as the only thing that doesn't work for us is the saturation, but 
> letting you configure *parts* of the emission is a bit too specific.


Would it be simpler instead just to have the logic contained in the virtual 
function for `TargetCodeGenInfo` as opposed to returning `nullptr` since any 
custom target will end up overriding it anyway and ideally not return `nullptr`?

In https://reviews.llvm.org/D50616#1203751, @rjmccall wrote:

> In https://reviews.llvm.org/D50616#1203692, @ebevhan wrote:
>
> > In https://reviews.llvm.org/D50616#1203446, @leonardchan wrote:
> >
> > > Sorry I forgot to address this also. Just to make sure I understand this 
> > > correctly since I haven't used these before: target hooks are essentially 
> > > for emitting target specific code for some operations right? Does this 
> > > mean that the `EmitFixedPointConversion` function should be moved to a 
> > > virtual method under `TargetCodeGenInfo` that can be overridden and this 
> > > is what get's called instead during conversion?
> >
> >
> > Yes, the thought I had was to have a virtual function in TargetCodeGenInfo 
> > that would be called first thing in EmitFixedPointConversion, and if it 
> > returns non-null it uses that value instead. It's a bit unfortunate in this 
> > instance as the only thing that doesn't work for us is the saturation, but 
> > letting you configure *parts* of the emission is a bit too specific.
> >
> > In https://reviews.llvm.org/D50616#1203635, @rjmccall wrote:
> >
> > > If this is more than just a hobby — like if there's a backend that wants 
> > > to do serious work with matching fixed-point operations to hardware 
> > > support — we should just add real LLVM IR support for fixed-point types 
> > > instead of adding a bunch of frontend customization hooks.  I don't know 
> > > what better opportunity we're expecting might come along to justify that, 
> > > and I don't think it's some incredibly onerous task to add a new leaf to 
> > > the LLVM type hierarchy.  Honestly, LLVM programmers across the board 
> > > have become far too accustomed to pushing things opaquely through an 
> > > uncooperative IR with an obscure muddle of intrinsics.
> > >
> > > In the meantime, we can continue working on this code.  Even if there's 
> > > eventually real IR support for fixed-point types, this code will still be 
> > > useful; it'll just become the core of some legalization pass in the 
> > > generic backend.
> >
> >
> > It definitely is; our downstream target requires it. As far as I know 
> > there's no real use case upstream, which is why it's likely quite hard to 
> > add any extensions to LLVM proper. Our implementation is done through 
> > intrinsics rather than an extension of the type system, as fixed-point 
> > numbers are really just integers under the hood. We've always wanted to 
> > upstream our fixed-point support (or some reasonable adaptation of it) but 
> > never gotten the impression that it would be possible since there's no 
> > upstream user.
> >
> > A mail I sent to the mailing list a while back has more details on our 
> > implementation, including what intrinsics we've added: 
> > http://lists.llvm.org/pipermail/cfe-dev/2018-May/058019.html We also have 
> > an LLVM pass that converts these intrinsics into pure IR, but it's likely 
> > that it won't work properly with some parts of this upstream design.
> >
> > Leonard's original proposal for this work has always been Clang-centric and 
> > never planned for implementing anything on the LLVM side, so we need to 
> > make due with what we get, but we would prefer as small a diff from 
> > upstream as possible.
>
>
> Has anyone actually asked LLVM whether they would accept fixed-point types 
> into IR?  I'm just a frontend guy, but it seems to me that there are 
> advantages to directly representing these operations in a portable way even 
> if there are no in-tree targets providing special support for them.  And 
> there are certainly in-tree targets that could provide such support if 
> someone was motivated to do it.


I haven't brought this up to llvm-dev, but the main reason for why we decided 
to only 

[PATCH] D50616: [Fixed Point Arithmetic] FixedPointCast

2018-08-20 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a comment.

I made a post on llvm-dev 
(http://lists.llvm.org/pipermail/llvm-dev/2018-August/125433.html) to see if 
other people have opinions on this. In the meantime, do you think I should make 
a separate patch that moves this into an LLVM intrinsic function?


Repository:
  rC Clang

https://reviews.llvm.org/D50616



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D49511: [Sema/Attribute] Check for noderef attribute

2018-08-21 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 161785.
leonardchan marked 6 inline comments as done and an inline comment as not done.

Repository:
  rC Clang

https://reviews.llvm.org/D49511

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/AST/TypePrinter.cpp
  lib/Parse/ParseExpr.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprMember.cpp
  lib/Sema/SemaType.cpp
  test/Frontend/noderef.c
  test/Frontend/noderef_on_non_pointers.cpp
  test/Frontend/noderef_on_non_pointers.m
  test/Frontend/noderef_templates.cpp

Index: test/Frontend/noderef_templates.cpp
===
--- /dev/null
+++ test/Frontend/noderef_templates.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+template 
+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}}
+}
+
+void func() {
+  float NODEREF *f;
+  int NODEREF *i;
+  func(f); // expected-note{{in instantiation of function template specialization 'func' requested here}}
+  func(i); // expected-note{{in instantiation of function template specialization 'func' requested here}}
+}
Index: test/Frontend/noderef_on_non_pointers.m
===
--- /dev/null
+++ test/Frontend/noderef_on_non_pointers.m
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+@interface NSObject
++ (id)new;
+@end
+
+void func() {
+  id NODEREF obj = [NSObject new]; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
Index: test/Frontend/noderef_on_non_pointers.cpp
===
--- /dev/null
+++ test/Frontend/noderef_on_non_pointers.cpp
@@ -0,0 +1,88 @@
+// RUN: %clang_cc1 -fblocks -verify %s
+
+/**
+ * Test 'noderef' attribute against other pointer-like types.
+ */
+
+#define NODEREF __attribute__((noderef))
+
+void Normal() {
+  int NODEREF i;// expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int NODEREF *i_ptr;   // ok
+  int NODEREF **i_ptr2; // ok
+  int *NODEREF i_ptr3;  // expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int *NODEREF *i_ptr4; // ok
+
+  auto NODEREF *auto_i_ptr = i_ptr;
+  auto NODEREF auto_i = i; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+
+  struct {
+int x;
+int y;
+  } NODEREF *s;
+
+  int __attribute__((noderef(10))) * no_args; // expected-error{{'noderef' attribute takes no arguments}}
+}
+
+const int NODEREF *const_i_ptr;
+static int NODEREF *static_i_ptr;
+
+void ParenTypes() {
+  int NODEREF(*i_ptr);// ok (same as `int NODEREF *`)
+  int NODEREF *(*i_ptr2); // ok (same as `int NODEREF **`)
+}
+
+// Function declarations
+int NODEREF func();   // expected-warning{{'noderef' can only be used on an array or pointer type}}
+int NODEREF *func2(); // ok (returning pointer)
+
+typedef int NODEREF (*func3)(int); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+typedef int NODEREF *(*func4)(int);
+
+void Arrays() {
+  int NODEREF i_arr[10];  // ok
+  int NODEREF i_arr2[10][10]; // ok
+  int NODEREF *i_arr3[10];// ok
+  int NODEREF i_arr4[] = {1, 2};
+}
+
+void ParenArrays() {
+  int NODEREF(i_ptr[10]);
+  int NODEREF(i_ptr2[10])[10];
+}
+
+typedef int NODEREF *(*func5[10])(int);
+
+// Arguments
+void func6(int NODEREF x); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+void func7(int NODEREF *x);
+void func8() NODEREF;
+
+void References() {
+  int x = 2;
+  int NODEREF &y = x; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int *xp = &x;
+  int NODEREF *&a = xp; // ok (reference to a NODEREF *)
+  int *NODEREF &b = xp; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+void BlockPointers() {
+  typedef int NODEREF (^IntBlock)(); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+class A {
+public:
+  int member;
+  int NODEREF *member2;
+  int NODEREF member3; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
+
+void MemberPointer() {
+  int NODEREF A::*var = &A::member; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+template 
+class B {
+  Ty NODEREF *member;
+  Ty NODEREF member2; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
Index: test/Frontend/noderef.c
===
--- /dev/null
+++ test/Frontend/noderef.c
@@ -0,0 +1,206 @@
+// RUN: %clang_cc1 -Wno-unused-value -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+struct

[PATCH] D49511: [Sema/Attribute] Check for noderef attribute

2018-08-21 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: lib/Parse/ParseExpr.cpp:1126
+
+Actions.StartCheckingNoDeref();
+

rsmith wrote:
> This parser-driven start/stop mechanism will not work in C++ templates. 
> Instead, can you remove the "start" part and check the noderef exprs as part 
> of popping the ExprEvaluationContextRecord?
I'm not sure if I should remove the the start and stop methods because for a 
regular C program, the Push/PopExprEvaluationContextRecord functions don't seem 
to be called, and even when they are called in C++, the initial record that 
exists on the stack isn't popped at all.

Since pending noderef expressions are still parsed and added to the last record 
during template instantiation, doing another check when popping covers all 
noderef exprs added during instantiation.



Comment at: lib/Sema/SemaExpr.cpp:14230-14242
+class DeclRefFinder : public ConstEvaluatedExprVisitor {
+public:
+  typedef ConstEvaluatedExprVisitor Inherited;
+
+  DeclRefFinder(ASTContext &Ctx) : Inherited(Ctx) {}
+
+  void VisitDeclRefExpr(const DeclRefExpr *E) { DeclRef = E; }

rsmith wrote:
> rsmith wrote:
> > I don't see any reason to assume that the `DeclRefExpr` found by this 
> > visitor will be the one you're interested in (the one the `noderef` 
> > attribute came from).
> > 
> > How about instead you walk over only expressions that you *know* preserve 
> > `noderef`, and if you can't find a declaration as the source of the 
> > `noderef` attribute, produce a differently-worded diagnostic that doesn't 
> > give a variable name?
> This comment is marked done but has not been addressed.
My bad. My response to this was adding a check in `StopCheckingNoDerefAndWarn` 
where we check if the `DeclRefExpr` is `nullptr` and throw the appropriate 
error if it is found or not.

Although I can't come up with an example where this doesn't get the declref we 
want, since the expressions we pass to this visitor are all our marked noderef 
expressions (which we check via the attribute on the type). So even if we have 
a complex expression that has multiple declrefs, all noderef declrefs should be 
checked by this.



Comment at: lib/Sema/SemaExpr.cpp:4291
+  const QualType &BaseTy = Base->getType();
+  QualType ElemTy;
+  if (const auto *ArrayTy = dyn_cast(BaseTy))

rsmith wrote:
> Did you mean to use ElemTy somewhere below? (I'd guess you intended to check 
> whether it's marked noderef?)
Forgot to remove this.



Comment at: lib/Sema/SemaType.cpp:4816
+
+if (const auto *AT = dyn_cast(T))
+  IsNoDeref = AT->getAttrKind() == AttributedType::attr_noderef;

rsmith wrote:
> rsmith wrote:
> > Move this after the check below (directly setting ExpectNoDerefChunk 
> > instead), and remove the unnecessary IsNoDeref variable.
> This is not correct: there could be multiple attributes at this level. You 
> could fix this locally either by looping through the attributes on the type 
> or iterating through the ParsedAttrs on the chunk. But I think my preference 
> would be to store state indicating that we have an unvalidated noderef 
> attribute on the TypeProcessingState at the point where you create the 
> AttributedType, and check and clear that flag here when creating a type chunk.
After https://reviews.llvm.org/D50526, it seems that the attribute can also be 
applied in `ConvertDeclSpecToType`, so I added another check for the attributes 
there.


Repository:
  rC Clang

https://reviews.llvm.org/D49511



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D49511: [Sema/Attribute] Check for noderef attribute

2018-08-21 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a comment.

In https://reviews.llvm.org/D49511#1206267, @rsmith wrote:

> In https://reviews.llvm.org/D49511#1206265, @rsmith wrote:
>
> > In https://reviews.llvm.org/D49511#1194716, @leonardchan wrote:
> >
> > > @rsmith any more feedback on this current version? If it still looks 
> > > incorrect to use the record this way, I don't mind simplifying it to work 
> > > on lvalue to rvalue conversions without checking for a leading address 
> > > space operation.
> >
> >
> > I've been thinking more about cleaner ways to implement this (and in 
> > particular, approaches that will provide more reasonable semantics in C++ 
> > -- allowing references to `noderef`, for example). We want to disallow 
> > operands of type `noderef T` to all operations by default, and only allow 
> > very specific operations on lvalues of type `noderef T` -- taking the 
> > address, performing member accesses, lvalue casts. The most natural way to 
> > get that effect would be to add a new form of placeholder type for a 
> > "dereferenced noderef" expression, that `CheckPlaceholderExpr` rejects, and 
> > that we add explicit support for in the contexts where such a construct is 
> > valid. (This is similar to how we handle overloaded function names and 
> > bound member function expressions in C++, for example.) (When we reach a 
> > context that "consumes" a dereferenced noderef expression, we'd need to go 
> > back and patch up its type, but I think that can be handled in a 
> > straightforward way.)
> >
> > I think we should also treat `noderef` more like a type qualifier: as an 
> > important example, if we have a pointer or reference to `noderef struct X`, 
> > then member access for a member of type `T` should give an lvalue of type 
> > `noderef T`.
>
>
> Sorry, I forgot to say: I do not think we need to do this for the initial 
> version of this functionality. This is mostly about cleanly extending the 
> functionality to cover more C++ constructs.


No problem. After this, I will make another patch that does this.


Repository:
  rC Clang

https://reviews.llvm.org/D49511



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D49511: [Sema/Attribute] Check for noderef attribute

2018-08-22 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 162126.
leonardchan marked 13 inline comments as done.

Repository:
  rC Clang

https://reviews.llvm.org/D49511

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/AST/TypePrinter.cpp
  lib/Parse/ParseExpr.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprMember.cpp
  lib/Sema/SemaType.cpp
  test/Frontend/noderef.c
  test/Frontend/noderef_on_non_pointers.cpp
  test/Frontend/noderef_on_non_pointers.m
  test/Frontend/noderef_templates.cpp

Index: test/Frontend/noderef_templates.cpp
===
--- /dev/null
+++ test/Frontend/noderef_templates.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+template 
+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}}
+}
+
+void func() {
+  float NODEREF *f;
+  int NODEREF *i;
+  func(f); // expected-note{{in instantiation of function template specialization 'func' requested here}}
+  func(i); // expected-note{{in instantiation of function template specialization 'func' requested here}}
+}
Index: test/Frontend/noderef_on_non_pointers.m
===
--- /dev/null
+++ test/Frontend/noderef_on_non_pointers.m
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+@interface NSObject
++ (id)new;
+@end
+
+void func() {
+  id NODEREF obj = [NSObject new]; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
Index: test/Frontend/noderef_on_non_pointers.cpp
===
--- /dev/null
+++ test/Frontend/noderef_on_non_pointers.cpp
@@ -0,0 +1,88 @@
+// RUN: %clang_cc1 -fblocks -verify %s
+
+/**
+ * Test 'noderef' attribute against other pointer-like types.
+ */
+
+#define NODEREF __attribute__((noderef))
+
+void Normal() {
+  int NODEREF i;// expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int NODEREF *i_ptr;   // ok
+  int NODEREF **i_ptr2; // ok
+  int *NODEREF i_ptr3;  // expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int *NODEREF *i_ptr4; // ok
+
+  auto NODEREF *auto_i_ptr = i_ptr;
+  auto NODEREF auto_i = i; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+
+  struct {
+int x;
+int y;
+  } NODEREF *s;
+
+  int __attribute__((noderef(10))) * no_args; // expected-error{{'noderef' attribute takes no arguments}}
+}
+
+const int NODEREF *const_i_ptr;
+static int NODEREF *static_i_ptr;
+
+void ParenTypes() {
+  int NODEREF(*i_ptr);// ok (same as `int NODEREF *`)
+  int NODEREF *(*i_ptr2); // ok (same as `int NODEREF **`)
+}
+
+// Function declarations
+int NODEREF func();   // expected-warning{{'noderef' can only be used on an array or pointer type}}
+int NODEREF *func2(); // ok (returning pointer)
+
+typedef int NODEREF (*func3)(int); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+typedef int NODEREF *(*func4)(int);
+
+void Arrays() {
+  int NODEREF i_arr[10];  // ok
+  int NODEREF i_arr2[10][10]; // ok
+  int NODEREF *i_arr3[10];// ok
+  int NODEREF i_arr4[] = {1, 2};
+}
+
+void ParenArrays() {
+  int NODEREF(i_ptr[10]);
+  int NODEREF(i_ptr2[10])[10];
+}
+
+typedef int NODEREF *(*func5[10])(int);
+
+// Arguments
+void func6(int NODEREF x); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+void func7(int NODEREF *x);
+void func8() NODEREF;
+
+void References() {
+  int x = 2;
+  int NODEREF &y = x; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+  int *xp = &x;
+  int NODEREF *&a = xp; // ok (reference to a NODEREF *)
+  int *NODEREF &b = xp; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+void BlockPointers() {
+  typedef int NODEREF (^IntBlock)(); // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+class A {
+public:
+  int member;
+  int NODEREF *member2;
+  int NODEREF member3; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
+
+void MemberPointer() {
+  int NODEREF A::*var = &A::member; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+}
+
+template 
+class B {
+  Ty NODEREF *member;
+  Ty NODEREF member2; // expected-warning{{'noderef' can only be used on an array or pointer type}}
+};
Index: test/Frontend/noderef.c
===
--- /dev/null
+++ test/Frontend/noderef.c
@@ -0,0 +1,206 @@
+// RUN: %clang_cc1 -Wno-unused-value -verify %s
+
+#define NODEREF __attribute__((noderef))
+
+struct S {
+  int a;
+  int b;
+};
+
+s

[PATCH] D49511: [Sema/Attribute] Check for noderef attribute

2018-08-22 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: lib/Parse/ParseExpr.cpp:1126
+
+Actions.StartCheckingNoDeref();
+

rsmith wrote:
> leonardchan wrote:
> > rsmith wrote:
> > > This parser-driven start/stop mechanism will not work in C++ templates. 
> > > Instead, can you remove the "start" part and check the noderef exprs as 
> > > part of popping the ExprEvaluationContextRecord?
> > I'm not sure if I should remove the the start and stop methods because for 
> > a regular C program, the Push/PopExprEvaluationContextRecord functions 
> > don't seem to be called, and even when they are called in C++, the initial 
> > record that exists on the stack isn't popped at all.
> > 
> > Since pending noderef expressions are still parsed and added to the last 
> > record during template instantiation, doing another check when popping 
> > covers all noderef exprs added during instantiation.
> `PushExpressionEvaluationContext` / `PopExpressionEvaluationContext` are 
> called regardless of which language we're parsing. If we're missing 
> `ExpressionEvaluationContext` records around some expression parsing, we 
> should fix that. We should never be creating expressions within the initial 
> `ExpressionEvaluationContext` record (except perhaps during error recovery).
> 
> > Since pending noderef expressions are still parsed and added to the last 
> > record during template instantiation, doing another check when popping 
> > covers all noderef exprs added during instantiation.
> 
> That's not how template instantiation works in Clang. We don't re-parse, we 
> perform a recursive tree transformation that does not involve the parser.
So when should a new `ExpressionEvaluationContext` be pushed or popped? 

For the following code:

```
#define NODEREF __attribute__((noderef))

void func(){
  int NODEREF *x;
  *x;
}

int main(){
  func();
}
```

A new context is pushed then popped in C++ but not for C. From what I can tell 
based off my observations and looking for where `Push/Pop` get called in code, 
new ones would get added when we enter a new GNU style statement expression, 
captured region after a pragma, or different error blocks.



Comment at: lib/Sema/SemaExpr.cpp:4289
+
+  if (TypeHasNoDeref(ResultTy)) {
+LastRecord.PossibleDerefs.insert(E);

rsmith wrote:
> Do you ensure that the `noderef` attribute will be on the innermost level of 
> the array type? I think you'll need to do so in order to warn on:
> 
> ```
> typedef int A[32];
> typedef A __attribute__((noderef)) *B;
> int f(B b) { return (*B)[1]; }
> ```
> 
> (Here, we have a pointer to a noderef annotated array of 
> non-noderef-annotated int. So I think we will not emit a warning from the 
> first dereference, because we have a pointer to an array, and we will not 
> emit a warning from the second dereference in the array indexing, because the 
> result type does not have the noderef attribute.)
H, so normally in order to check what's correct, I usually run these 
examples through `sparse` since that's the tool that actually checks `noderef` 
for gcc, but it seems that sparse instead diagnoses a warning on the array 
indexing instead and nothing for the first dereference.

This shouldn't be though since, as you pointed out, the array does not have 
`noderef` types. For a simple array,

```
int __attribute__((noderef)) x[10];
x[0];
```

`sparse` diagnoses the appropriate warning for the array index. Personally 
though, I would chalk this up to an edge case that wasn't thought of before in 
sparse, since something like this isn't handled on their existing validation 
tests.

Currently, this diagnoses a warning on the first dereference, but I can also 
understand why it shouldn't warn because accessing `noderef` structs shouldn't 
warn if the member accessed is an array. The only case though this applies in 
sparse's tests are with structs and they don't provide a test for dereferencing 
a pointer to an array.

I think the reason for why the struct example still passes is that if the 
member is an array, none of the actual data in the struct is being accessed. 
Instead, the value returned is just a pointer to the start of the array within 
the struct and equivalent to just adding an offset to the struct pointer. I 
think that no warning should also be thrown for this example if it is 
guaranteed that array `A` can similarly be found from simple pointer arithmetic 
on pointer `B`. I don't think it can unless B were an array or struct also, but 
I could be wrong or overthinking this.


Repository:
  rC Clang

https://reviews.llvm.org/D49511



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D46084: Addition of the Fixed Point _Accum type

2018-05-09 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 145993.
leonardchan added a comment.

- Restrict usage of fixed point types only to C


https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -542,6 +548,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/accum_errors.cpp
===
--- /dev/null
+++ test/Frontend/accum_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;// expected-error{{Fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;// expected-error{{Fixed point types are only allowed in C}}
+unsigned _Accum u_accum;// expected-error{{Fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+
+short _Accum short_accum;   // expected-error{{Fixed point types are only allowed in C}}
+_Accum accum;   // expected-error{{Fixed point types are only allowed in C}}
+long _Accum long_accum; // expected-error{{Fixed point types are only allowed in C}}
Index: test/Frontend/accum_errors.c
===
--- /dev/null
+++ test/Frontend/accum_errors.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
Index: test/Frontend/accum.c
===
--- /dev/null
+++ test/Frontend/accum.c
@@ -0,0 +1,26 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+/*  Various contexts where type _Accum can appear. */
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+
+//CHECK:  |-VarDecl {{.*}} s_short_accum 'short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum'
+//CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum'
+//CHECK-NEXT: `-VarDecl {{.*}} long_accum 'long _Accum'
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -6816,6 +6816,24 @@
 case PREDEF_TYPE_LONGDOUBLE_ID:
   T = Context.LongDoubleTy;
   break;
+case PREDEF_TYPE_SHORT_ACCUM_ID:
+  T = Context.ShortAccumTy;
+  break;
+case PREDEF_TYPE_ACCUM_ID:
+  T = Context.Acc

[PATCH] D46911: Addition of the remaining fixed point types and their saturated equivalents

2018-05-15 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added a project: clang.

This diff includes changes for the remaining _Fract and _Sat fixed point types.

  signed short _Fract s_short_fract;
  signed _Fract s_fract;
  signed long _Fract s_long_fract;
  unsigned short _Fract u_short_fract;
  unsigned _Fract u_fract;
  unsigned long _Fract u_long_fract;
  
  // Aliased fixed point types
  short _Accum short_accum;
  _Accum accum;
  long _Accum long_accum;
  short _Fract short_fract;
  _Fract fract;
  long _Fract long_fract;
  
  // Saturated fixed point types
  _Sat signed short _Accum sat_s_short_accum;
  _Sat signed _Accum sat_s_accum;
  _Sat signed long _Accum sat_s_long_accum;
  _Sat unsigned short _Accum sat_u_short_accum;
  _Sat unsigned _Accum sat_u_accum;
  _Sat unsigned long _Accum sat_u_long_accum;
  _Sat signed short _Fract sat_s_short_fract;
  _Sat signed _Fract sat_s_fract;
  _Sat signed long _Fract sat_s_long_fract;
  _Sat unsigned short _Fract sat_u_short_fract;
  _Sat unsigned _Fract sat_u_fract;
  _Sat unsigned long _Fract sat_u_long_fract;
  
  // Aliased saturated fixed point types
  _Sat short _Accum sat_short_accum;
  _Sat _Accum sat_accum;
  _Sat long _Accum sat_long_accum;
  _Sat short _Fract sat_short_fract;
  _Sat _Fract sat_fract;
  _Sat long _Fract sat_long_fract;

This diff only allows for declaration of these fixed point types. Assignment 
and other operations done on fixed point types according to 
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf will be added in 
future patches.

This is a parent of https://reviews.llvm.org/D46084


Repository:
  rC Clang

https://reviews.llvm.org/D46911

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_errors.cpp

Index: test/Frontend/fixed_point_errors.c
===
--- /dev/null
+++ test/Frontend/fixed_point_errors.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+long long _Fract longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+unsigned long long _Fract u_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+
+_Sat int i;  // expected-error{{'int' cannot be saturated. Only _Fract and _Accum can.}}
+_Sat _Sat _Fract fract;  // expected-warning{{duplicate '_Sat' declaration specifier}}
+
+_Sat long long _Accum sat_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+_Sat unsigned long long _Accum sat_u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+_Sat long long _Fract sat_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+_Sat unsigned long long _Fract sat_u_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
Index: test/Frontend/fixed_point.c
===
--- /dev/null
+++ test/Frontend/fixed_point.c
@@ -0,0 +1,82 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+signed short _Fract s_short_fract;
+signed _Fract s_fract;
+signed long _Fract s_long_fract;
+unsigned short _Fract u_short_fract;
+unsigned _Fract u_fract;
+unsigned long _Fract u_long_fract;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+short _Fract short_fract;
+_Fract fract;
+long _Fract long_fract;
+
+// Saturated fixed point types
+_Sat signed short _Accum sat_s_short_accum;
+_Sat signed _Accum sat_s_accum;
+_Sat signed long _Accum sat_s_long_accum;
+_Sat unsigned short _Accum sat_u_short_accum;
+_Sat unsigned _Accum sat_u_accum;
+_Sat unsigned long _Accum sat_u_long_accum;
+_Sat signed short _Fract sat_s_short_fract;
+_Sat signed _Fract sat_s_

[PATCH] D46915: Set Fixed Point Precision Bits and Create Fixed Point Literals

2018-05-15 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.
Herald added a subscriber: mgorny.

This diff includes the logic for setting the precision bits for each primary 
fixed point type when building clang and logic for initializing a fixed point 
literal.

The precision bits are set when building cmake via the flags

  SACCUM_FBIT
  ACCUM_FBIT
  LACCUM_FBIT
  ...

More checks to ensure the bit values used are valid will be added in future 
patches.

Fixed point literals are declared using the suffixes

  hr: short _Fract
  uhr: unsigned short _Fract
  r: _Fract
  ur: unsigned _Fract
  lr: long _Fract
  ulr: unsigned long _Fract
  hk: short _Accum
  uhk: unsigned short _Accum
  k: _Accum
  uk: unsigned _Accum

Errors are also thrown for literal values that exceed the range of the type 
corresponding to the suffix

  unsigned short _Accum u_short_accum = 256.0uhk;   // expected-error{{the 
integral part of this literal is too large for this unsigned _Accum type}}

This is a parent of https://reviews.llvm.org/D46911


Repository:
  rC Clang

https://reviews.llvm.org/D46915

Files:
  CMakeLists.txt
  cmake/modules/InitFixedPointBits.cmake
  include/clang/AST/Expr.h
  include/clang/AST/OperationKinds.def
  include/clang/AST/RecursiveASTVisitor.h
  include/clang/AST/Type.h
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/FixedPoint.h.in
  include/clang/Basic/StmtNodes.td
  include/clang/Lex/LiteralSupport.h
  lib/AST/ASTContext.cpp
  lib/AST/ASTDumper.cpp
  lib/AST/Expr.cpp
  lib/AST/ExprClassification.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/StmtPrinter.cpp
  lib/AST/StmtProfile.cpp
  lib/AST/Type.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Lex/LiteralSupport.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExceptionSpec.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_declarations.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_validation.c
  tools/libclang/CXCursor.cpp

Index: tools/libclang/CXCursor.cpp
===
--- tools/libclang/CXCursor.cpp
+++ tools/libclang/CXCursor.cpp
@@ -305,6 +305,10 @@
 K = CXCursor_IntegerLiteral;
 break;
 
+  case Stmt::FixedPointLiteralClass:
+llvm_unreachable("No cursor for FixedPointLiteralClass");
+break;
+
   case Stmt::FloatingLiteralClass:
 K = CXCursor_FloatingLiteral;
 break;
Index: test/Frontend/fixed_point_validation.c
===
--- /dev/null
+++ test/Frontend/fixed_point_validation.c
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -S -emit-llvm -o - %s | lli
+
+// Run simple validation tests
+
+#define assert(b) if (!(b)) { return 1; }
+
+int main(){
+  short _Accum s_accum;
+  short _Accum s_accum2 = 2.0hk;
+  short _Fract s_fract = 0.999hr;
+  short _Fract s_fract2 = -0.999hr;
+
+  assert(s_accum == 0);
+
+  s_accum = s_accum2;
+
+  assert(s_accum == s_accum2);
+  assert(s_accum == 2);
+}
Index: test/Frontend/fixed_point_errors.c
===
--- test/Frontend/fixed_point_errors.c
+++ test/Frontend/fixed_point_errors.c
@@ -1,14 +1,23 @@
 // RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
 
-long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
-unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
-long long _Fract longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
-unsigned long long _Fract u_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;   // expected-error{{'long long _Accum' is invalid}}
+long long _Fract longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+unsigned long long _Fract u_longlong_fract;   // expected-error{{'long long _Fract' is invalid}}
 
 _Sat int i;  // expected-error{{'int' cannot be saturated. Only _Fract and _Accum can.}}
 _Sat _Sat _Fract fract;  // expected-warning{{duplicate '_Sat' declaration specifier}}
 
-_Sat long long _Accum sat_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+_Sat long long _Accum sat_longlong_accum; // expected-error{{'long long _Accum' is invalid}}
 _Sat unsigned long long _Accum sat_u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
-_Sat long long _Fract sat_longlong_fract;  // expected-error{

[PATCH] D46917: Comparison and Unary Operations for Fixed Point Types

2018-05-15 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr.
leonardchan added a project: clang.

This patch contains logic and tests for different unary and comparison 
operations on fixed point types, and casting between integers and fixed point 
types.

The operations are `==`, `!=`, `>`, `<`, `>=`, `<=`, `!`, `+`, `-`, `++`, and 
`--`.

`~` is not a supported operation on fixed point types.

This is a parent of https://reviews.llvm.org/D46915


Repository:
  rC Clang

https://reviews.llvm.org/D46917

Files:
  lib/CodeGen/CGExprScalar.cpp
  lib/Sema/SemaExpr.cpp
  test/Frontend/fixed_point_declarations.c
  test/Frontend/fixed_point_validation.c

Index: test/Frontend/fixed_point_validation.c
===
--- test/Frontend/fixed_point_validation.c
+++ test/Frontend/fixed_point_validation.c
@@ -1,19 +1,170 @@
+// RUN: %clang -S -emit-llvm %s -o - | FileCheck %s
 // RUN: %clang_cc1 -S -emit-llvm -o - %s | lli
 
+// The first test checks the emitted llvm IR.
+// The second test checks the output.
+// Both these test require that the default bit widths for the fixed point types
+// are used since we check for bit shifted literals that were converted from
+// ints and floats.
+
+// Primary fixed point types
+signed short _Accum s_short_accum;// CHECK-DAG: @s_short_accum =  common dso_local global i16 0, align 2
+signed _Accum s_accum;// CHECK-DAG: @s_accum =common dso_local global i32 0, align 4
+signed long _Accum s_long_accum;  // CHECK-DAG: @s_long_accum =   common dso_local global i64 0, align 8
+unsigned short _Accum u_short_accum;  // CHECK-DAG: @u_short_accum =  common dso_local global i16 0, align 2
+unsigned _Accum u_accum;  // CHECK-DAG: @u_accum =common dso_local global i32 0, align 4
+unsigned long _Accum u_long_accum;// CHECK-DAG: @u_long_accum =   common dso_local global i64 0, align 8
+signed short _Fract s_short_fract;// CHECK-DAG: @s_short_fract =  common dso_local global i16 0, align 2
+signed _Fract s_fract;// CHECK-DAG: @s_fract =common dso_local global i32 0, align 4
+signed long _Fract s_long_fract;  // CHECK-DAG: @s_long_fract =   common dso_local global i64 0, align 8
+unsigned short _Fract u_short_fract;  // CHECK-DAG: @u_short_fract =  common dso_local global i16 0, align 2
+unsigned _Fract u_fract;  // CHECK-DAG: @u_fract =common dso_local global i32 0, align 4
+unsigned long _Fract u_long_fract;// CHECK-DAG: @u_long_fract =   common dso_local global i64 0, align 8
+
+// There are 7 bits allocated to the fractional part and 8
+// bits allocated to the integral part of a short _Accum by default.
+
+signed short _Accum s_short_accum2 = 2.5hk;  // CHECK-DAG: @s_short_accum2 = dso_local global i16 320, align 2
+short _Fract short_fract = 0.333hr;  // CHECK-DAG: @short_fract = dso_local global i16 42, align 2
+
 // Run simple validation tests
 
 #define assert(b) if (!(b)) { return 1; }
 
 int main(){
-  short _Accum s_accum;
+  short _Accum s_accum = 0.0hk;
   short _Accum s_accum2 = 2.0hk;
   short _Fract s_fract = 0.999hr;
   short _Fract s_fract2 = -0.999hr;
+  const _Fract fract_zero = 0.0r;
+  // CHECK:  %s_accum = alloca i16, align 2
+  // CHECK:  %s_accum2 = alloca i16, align 2
+  // CHECK:  %s_fract = alloca i16, align 2
+  // CHECK:  %s_fract2 = alloca i16, align 2
+  // CHECK:  %fract_zero = alloca i32, align 4
+  // CHECK:  store i16 0, i16* %s_accum, align 2
+  // CHECK:  store i16 256, i16* %s_accum2, align 2
+  // CHECK:  store i16 127, i16* %s_fract, align 2
+  // CHECK:  store i16 -127, i16* %s_fract2, align 2
+  // CHECK:  store i32 0, i32* %fract_zero, align 4
+
+  / Simple Comparisons ***/
 
   assert(s_accum == 0);
+  // CHECK:  {{.*}} = load i16, i16* %s_accum, align 2
+  // CHECK-NEXT: {{.*}} = icmp eq i16 {{.*}}, 0
 
   s_accum = s_accum2;
+  // CHECK:  {{.*}} = load i16, i16* %s_accum2, align 2
+  // CHECK-NEXT: store i16 %1, i16* %s_accum, align 2
 
   assert(s_accum == s_accum2);
+  // CHECK:  {{.*}} = load i16, i16* %s_accum, align 2
+  // CHECK-NEXT: {{.*}} = load i16, i16* %s_accum2, align 2
+  // CHECK-NEXT: {{.*}} = icmp eq i16 {{.*}}, {{.*}}
+
+  assert(s_accum2 == s_accum);
+  // CHECK:  {{.*}} = load i16, i16* %s_accum2, align 2
+  // CHECK-NEXT: {{.*}} = load i16, i16* %s_accum, align 2
+  // CHECK-NEXT: {{.*}} = icmp eq i16 {{.*}}, {{.*}}
+
   assert(s_accum == 2);
+  // CHECK:  {{.*}} = icmp eq i16 {{.*}}, 256
+
+  assert(2 == s_accum);
+  // CHECK:  {{.*}} = icmp eq i16 256, {{.*}}
+
+  int x = 2;
+  assert(s_accum == x);
+  // CHECK:  {{.*}} = load i32, i32* %x, align 4
+  // CHECK-NEXT: {{.*}} = trunc i32 {{.*}} to i16
+  // CHECK-NEXT: {{.*}} = shl i16 {{.*}}, 7
+  // CHECK-NEXT: {{.*}} = icmp eq i16 {{.*}}, {{.*}}
+
+  assert(x == s_accum);
+
+  assert(s_accum

[PATCH] D46925: Remaining Binary Operations on Primary Fixed Point Types

2018-05-15 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.

This patch implements the remaining arithmetic and logical operations on the 
primary fixed point types.

The operations are `+`, `-`, `*`, `/`, `<<`, and `>>`.

  // Addition
   s_accum = 3.0hk;
   short _Accum s_accum_sum = s_accum + s_accum2;
   assert(s_accum_sum == 5);
   assert(s_fract + s_fract2 == 0);
  
   // Subtraction
   short _Accum s_accum_diff = s_accum - s_accum2;
   assert(s_accum_diff == 1);
   assert(s_accum2 - s_accum == -1);
  
   // Multiplication
   short _Accum s_accum_mul = s_accum * s_accum2;
   assert(s_accum_mul == 6);
   assert(2.0hk * 3.0hk == 6);
   assert(2.0hk * 3 == 6);
   assert(2.5hk * 3 == 7.5k);
   assert(-2.5hk * 3 == -7.5lk);
   assert(3 * -2.5hk == -7.5hk);
   assert(-2.5hk * 0 == 0);
  
   // Division
   const short _Accum s_accum3 = 2.5hk;
   short _Accum s_accum_div = s_accum3 / s_accum2;
   assert(s_accum_div == 1.25hk);
   assert(5.0hk / s_accum3 == 2);
   assert(-5.0hk / s_accum3 == -2);
   assert(9.9k / 3.3k == 3);
   assert(9.9hk / 3.3k != 3);  // We lose precision when converting between 
types of different
   // fractional width.
   assert(6.75hk / 2.25k == 3);  // Unless the fractional part can be evenly 
represented with
 // sums of powers of 2.
   assert(0 / 2.0hk == 0);

`%` is not a valod operation on fixed point types.

This is the parent of https://reviews.llvm.org/D46917


Repository:
  rC Clang

https://reviews.llvm.org/D46925

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/OperationKinds.def
  include/clang/AST/Type.h
  lib/AST/ASTContext.cpp
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Type.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Sema/SemaExpr.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point_validation.c

Index: test/Frontend/fixed_point_validation.c
===
--- test/Frontend/fixed_point_validation.c
+++ test/Frontend/fixed_point_validation.c
@@ -1,5 +1,5 @@
-// RUN: %clang -S -emit-llvm %s -o - | FileCheck %s
 // RUN: %clang_cc1 -S -emit-llvm -o - %s | lli
+// RUN: %clang -S -emit-llvm %s -o - | FileCheck %s
 
 // The first test checks the emitted llvm IR.
 // The second test checks the output.
@@ -74,6 +74,9 @@
   assert(2 == s_accum);
   // CHECK:  {{.*}} = icmp eq i16 256, {{.*}}
 
+  assert(2 == 2.0hk);
+  assert(2 != 2.01hk);
+
   int x = 2;
   assert(s_accum == x);
   // CHECK:  {{.*}} = load i32, i32* %x, align 4
@@ -128,6 +131,46 @@
   // numbers.
   assert(2 == 2.001hk);  // This is valid if SACCUM_FBITS == 7
 
+  // Comparisons between fixed-point types
+  // Signed _Accum to signed _Accum types.
+  assert(2.5hk == 2.5k);
+  assert(2.5k == 2.5lk);
+  assert(-2.5hk == -2.5k);
+  assert(-2.5k == -2.5lk);
+
+  // Unsigned _Accum to unigned _Accum
+  assert(2.5uhk == 2.5uk);
+  assert(2.5uk == 2.5ulk);
+
+  // Signed _Fract to signed _Fract types.
+  assert(0.333hr != 0.333r);  // Loss of precision since different fractional widths
+  assert(0.333r != 0.333lr);
+  assert(-0.333hr != -0.333r);
+  assert(-0.333r != -0.333lr);
+
+  // Unsigned _Fract to unsigned _Fract types.
+  assert(0.333uhr != 0.333ur);
+  assert(0.333ur != 0.333ulr);
+
+  // Signed _Accum to signed _Fract
+  assert(0.333hk == 0.333hr);
+  assert(0.333k == 0.333r);
+  assert(0.333lk == 0.333lr);
+  assert(0.333hk == 0.333r);  // Although _Fract has higher precision, it gets casted up to
+  // short _Accum which (using default precisions)
+  // has fewer fractional bits.
+
+  // Signed _Accum to unsigned _Fract
+  assert(0.333hk == 0.333uhr);
+  assert(0.333k == 0.333ur);
+  assert(0.333lk == 0.333ulr);
+
+  // Signed _Accum to unsigned _Accum
+  assert(2.5hk == 2.5uhk);
+  assert(2.5k == 2.5uk);
+  assert(2.5lk == 2.5ulk);
+
+
   / Unary operations ***/
 
   s_accum = 0.0hk;
@@ -167,4 +210,58 @@
   assert(+s_fract == s_fract);
   assert(+s_fract2 == s_fract2);  // s_fract2 is negative
   assert(-s_fract == s_fract2);
+
+  / Binary operations ***/
+
+  // Addition
+  s_accum = 3.0hk;
+  short _Accum s_accum_sum = s_accum + s_accum2;
+  assert(s_accum_sum == 5);
+  assert(s_fract + s_fract2 == 0);
+
+  // Subtraction
+  short _Accum s_accum_diff = s_accum - s_accum2;
+  assert(s_accum_diff == 1);
+  assert(s_accum2 - s_accum == -1);
+
+  // Multiplication
+  short _Accum s_accum_mul = s_accum * s_accum2;
+  assert(s_accum_mul == 6);
+  assert(2.0hk * 3.0hk == 6);
+  assert(2.0hk * 3 == 6);
+  assert(2.5hk * 3 == 7.5k);
+  assert(-2.5hk * 3 == -7.5lk);
+  assert(3 * -2.5hk == -7.5hk);
+  assert(-2.5hk * 

[PATCH] D46926: Conversion between Fixed Point and Floating Point Numbers

2018-05-15 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.

This patch has the implementation and tests for converting between fixed point 
and floating point numbers.

The conversion process is simply dividing the fixed point value, as an integer, 
by 2^(# of fractional bits) as a float.

This is a parent of https://reviews.llvm.org/D46925


Repository:
  rC Clang

https://reviews.llvm.org/D46926

Files:
  include/clang/AST/OperationKinds.def
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Sema/SemaCast.cpp
  lib/Sema/SemaExpr.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point_validation.c

Index: test/Frontend/fixed_point_validation.c
===
--- test/Frontend/fixed_point_validation.c
+++ test/Frontend/fixed_point_validation.c
@@ -30,6 +30,7 @@
 // Run simple validation tests
 
 #define assert(b) if (!(b)) { return 1; }
+#define abs(x) x < 0 ? -x : x
 
 int main(){
   short _Accum s_accum = 0.0hk;
@@ -264,4 +265,18 @@
   assert(5.0hk >> 2 == 1.25hk);
   assert(-5.0hk >> 2 == -1.25k);
   assert(0.0hr >> 2 == 0);
+
+  / Float conversions ***/
+
+  float f = (float)2.5k;
+  assert(f > 2.4999 && f < 2.5001);  // High precision since the fractional value can be evenly
+ // represented.
+  assert((float)2.333hk != 2.333f);
+
+  float base = 2.333f;
+  float saccum_diff = abs(base - 2.333hk);
+  float accum_diff = abs(base - 2.333k);
+  float laccum_diff = abs(base - 2.333lk);
+  assert(accum_diff < saccum_diff);
+  assert(laccum_diff < accum_diff);
 }
Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp
===
--- lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -321,6 +321,7 @@
 const LocationContext *LCtx = Pred->getLocationContext();
 
 switch (CastE->getCastKind()) {
+  case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating");
   case CK_IntegralToFixedPoint: llvm_unreachable("ExprEngine::VisitCast CK_IntegralToFixedPoint"); // TODO
   case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO
   case CK_LValueToRValue:
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -1029,6 +1029,18 @@
   return result;
 }
 
+/// \brief Handle arithmetic conversion from fixed point to floating.  Helper function
+/// of UsualArithmeticConversions()
+static QualType handleFixedPointToFloatConversion(Sema &S, ExprResult &FloatExpr,
+  ExprResult &FixedPointExpr,
+  QualType FloatTy, QualType FixedPointTy) {
+  assert(FloatTy->isFloatingType());
+  assert(FixedPointTy->isFixedPointType());
+
+  FixedPointExpr = S.ImpCastExprToType(FixedPointExpr.get(), FloatTy, CK_FixedPointToFloating);
+  return FloatTy;
+}
+
 /// \brief Handle arithmethic conversion with floating point types.  Helper
 /// function of UsualArithmeticConversions()
 static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
@@ -1057,11 +1069,22 @@
 if (LHSType->isHalfType() && !S.getLangOpts().NativeHalfType)
   LHSType = S.Context.FloatTy;
 
+if (RHSType->isFixedPointType()) {
+  return handleFixedPointToFloatConversion(S, LHS, RHS, LHSType,
+   RHSType);
+}
+
 return handleIntToFloatConversion(S, LHS, RHS, LHSType, RHSType,
   /*convertFloat=*/!IsCompAssign,
   /*convertInt=*/ true);
   }
   assert(RHSFloat);
+
+  if (LHSType->isFixedPointType()) {
+return handleFixedPointToFloatConversion(S, RHS, LHS, RHSType,
+ LHSType);
+  }
+
   return handleIntToFloatConversion(S, RHS, LHS, RHSType, LHSType,
 /*convertInt=*/ true,
 /*convertFloat=*/!IsCompAssign);
@@ -1218,6 +1241,7 @@
   CK_IntegralRealToComplex);
   return ComplexType;
 }
+
 /// \brief Handle arithmetic conversion from integer to fixed point.  Helper function
 /// of UsualArithmeticConversions()
 static QualType handleIntToFixedPointConversion(Sema &S, ExprResult &FixedPointExpr,
@@ -6028,7 +6052,14 @@
 }
 llvm_unreachable("Should have returned before this");
 
-  case Type::STK_FixedPoint: llvm_unreachable("Sema::PrepareScalarCast from STK_FixedPoint to anything");  // TODO
+  case Type::STK_F

[PATCH] D46927: Augmented Assignment for Fixed Point Types

2018-05-15 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.

This patch contains the changes and tests for augmented assignments for primary 
fixed point types.

  s_accum = 7.5hk;
  s_accum2 = 2.0hk;
  s_accum += s_accum2;
  assert(s_accum == 9.5hk);
  s_accum += 2.5k;
  assert(s_accum == 12);

This is a parent of https://reviews.llvm.org/D46926


Repository:
  rC Clang

https://reviews.llvm.org/D46927

Files:
  include/clang/AST/Type.h
  lib/AST/Type.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Sema/SemaExpr.cpp
  test/Frontend/fixed_point_validation.c

Index: test/Frontend/fixed_point_validation.c
===
--- test/Frontend/fixed_point_validation.c
+++ test/Frontend/fixed_point_validation.c
@@ -279,4 +279,35 @@
   float laccum_diff = abs(base - 2.333lk);
   assert(accum_diff < saccum_diff);
   assert(laccum_diff < accum_diff);
+
+  / Auxillary assignments ***/
+
+  s_accum = 7.5hk;
+  s_accum2 = 2.0hk;
+  s_accum += s_accum2;
+  assert(s_accum == 9.5hk);
+  s_accum += 2.5k;
+  assert(s_accum == 12);
+
+  s_accum -= s_accum2;
+  assert(s_accum == 10);
+  s_accum -= 2.5lk;
+  assert(s_accum == 7.5k);
+
+  s_accum2 = 3.0k;
+  s_accum *= s_accum2;
+  assert(s_accum == 22.5k);
+  s_accum *= 0.5r;
+  assert(s_accum == 11.25hk);
+
+  s_accum /= s_accum2;
+  assert(s_accum == 3.75k);
+  s_accum /= 0.5hr;
+  assert(s_accum == 7.5k);
+
+  s_accum <<= 3;
+  assert(s_accum == 60);
+
+  s_accum >>= 3;
+  assert(s_accum == 7.5k);
 }
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -6057,7 +6057,7 @@
   default: llvm_unreachable("Unable to convert from fixed point type");
   case Type::STK_Integral: llvm_unreachable("Unimplemented scalar cast from fixed point to int");  // TODO
   case Type::STK_Floating: return CK_FixedPointToFloating;
-  case Type::STK_FixedPoint: llvm_unreachable("Unimplemented scalar cast from fixed point to fixed point");  // TODO
+  case Type::STK_FixedPoint: return CK_FixedPointCast;
 }
   }
 
Index: lib/CodeGen/CGExprScalar.cpp
===
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -308,6 +308,17 @@
   Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
   SourceLocation Loc, bool TreatBooleanAsSigned);
 
+  /// Emit a conversion between fixed point types by moving the radix point.
+  /// This does not take into account resizing of the underlying llvm type
+  /// which should be handled either before or after calling this function.
+  /// 
+  /// If the type is being scaled up, this method should be called after
+  /// performing an intcast. If the type is scaled down, this method should be
+  /// called before performing an intcast. This is necessary such that the
+  /// shift operations retain as much of the original data as possible before
+  /// truncation or after extension.
+  Value *EmitFixedPointRadixShift(Value *Src, QualType SrcTy, QualType DstTy);
+
   /// Emit a conversion from the specified complex type to the specified
   /// destination type, where the destination type is an LLVM scalar type.
   Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
@@ -957,6 +968,50 @@
 SanitizerHandler::FloatCastOverflow, StaticArgs, OrigSrc);
 }
 
+
+/// Emit a conversion between fixed point types by moving the radix point.
+/// This does not take into account resizing of the underlying llvm type
+/// which should be handled either before or after calling this function.
+/// 
+/// If the type is being scaled up, this method should be called after
+/// performing an intcast. If the type is scaled down, this method should be
+/// called before performing an intcast. This is necessary such that the
+/// shift operations retain as much of the original data as possible before
+/// truncation or after extension.
+Value *ScalarExprEmitter::EmitFixedPointRadixShift(Value *Src, QualType SrcTy,
+   QualType DstTy) {
+  assert(DstTy->isFixedPointType());
+  assert(SrcTy->isFixedPointType());
+
+  Value* Res = Src;
+
+  // Casting between fixed point types involves separating the integral and
+  // fractional bits, potentially shifting them, then joining back together.
+  unsigned dest_fbits = getFixedPointFBits(DstTy);
+  unsigned src_fbits = getFixedPointFBits(SrcTy);
+  unsigned dest_ibits = getFixedPointIBits(DstTy);
+  unsigned src_ibits = getFixedPointIBits(SrcTy);
+
+  // If the number of integral bits is decreasing, trim off any extra bits while
+  // retaining the sign.
+  if (dest_ibits < src_ibits) {
+Res = Builder.CreateShl(Res, src_ibits - dest_ibits);
+Res = Builder.CreateAShr(Res, src_ibits - dest

[PATCH] D46960: [Fixed Point Arithmetic] Predefined Precision Macros

2018-05-16 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.

This patch contains the addition of the precision macros for integral and 
fractional bits according to clause 7.18a.3 of 
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf. The macros are 
integer constants and added as predefined macros.

  // Fractional bits of _Accum types
  __SACCUM_FBIT__
  __ACCUM_FBIT__
  __LACCUM_FBIT__
  __USACCUM_FBIT__
  __UACCUM_FBIT__
  __ULACCUM_FBIT__
  
  // Fractional bits of _Fract types
  __SFRACT_FBIT__
  __FRACT_FBIT__
  __LFRACT_FBIT__
  __USFRACT_FBIT__
  __UFRACT_FBIT__
  __ULFRACT_FBIT__
  
  // Integral bits of _Accum types
  __SACCUM_IBIT__
  __ACCUM_IBIT__
  __LACCUM_IBIT__
  __USACCUM_IBIT__
  __UACCUM_IBIT__
  __ULACCUM_IBIT__

This is a child of https://reviews.llvm.org/D46927


Repository:
  rC Clang

https://reviews.llvm.org/D46960

Files:
  include/clang/Lex/Preprocessor.h
  lib/Lex/PPMacroExpansion.cpp
  test/Frontend/fixed_point_builtin_macros.c

Index: test/Frontend/fixed_point_builtin_macros.c
===
--- /dev/null
+++ test/Frontend/fixed_point_builtin_macros.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -S -emit-llvm -o - %s | lli
+
+#define assert(b) if (!(b)) { return 1; }
+
+int main() {
+  // Test using the recommended values for a typical desktop processor (Annex
+  // A.3). These are also the default values when building clang.
+  // Fractional bits of _Accum types
+  assert(__SACCUM_FBIT__  == 7);
+  assert(__ACCUM_FBIT__   == 15);
+  assert(__LACCUM_FBIT__  == 31);
+  assert(__USACCUM_FBIT__ == 8);
+  assert(__UACCUM_FBIT__  == 16);
+  assert(__ULACCUM_FBIT__ == 32);
+
+  // Fractional bits of _Fract types
+  assert(__SFRACT_FBIT__  == 7);
+  assert(__FRACT_FBIT__   == 15);
+  assert(__LFRACT_FBIT__  == 31);
+  assert(__USFRACT_FBIT__ == 8);
+  assert(__UFRACT_FBIT__  == 16);
+  assert(__ULFRACT_FBIT__ == 32);
+
+  // Integral bits of _Accum types
+  assert(__SACCUM_IBIT__  == 8);
+  assert(__ACCUM_IBIT__   == 16);
+  assert(__LACCUM_IBIT__  == 32);
+  assert(__USACCUM_IBIT__ == 8);
+  assert(__UACCUM_IBIT__  == 16);
+  assert(__ULACCUM_IBIT__ == 32);
+}
Index: lib/Lex/PPMacroExpansion.cpp
===
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -14,6 +14,7 @@
 
 #include "clang/Basic/Attributes.h"
 #include "clang/Basic/FileManager.h"
+#include "clang/Basic/FixedPoint.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/LangOptions.h"
@@ -355,6 +356,31 @@
   Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro(*this, "__INCLUDE_LEVEL__");
   Ident__TIMESTAMP__ = RegisterBuiltinMacro(*this, "__TIMESTAMP__");
 
+  // Fixed point macros (ISO/IEC JTC1 SC22 WG14 N1169)
+  // Fractional bits of _Accum types
+  Ident__SACCUM_FBIT__   = RegisterBuiltinMacro(*this, "__SACCUM_FBIT__");
+  Ident__ACCUM_FBIT__= RegisterBuiltinMacro(*this, "__ACCUM_FBIT__");
+  Ident__LACCUM_FBIT__   = RegisterBuiltinMacro(*this, "__LACCUM_FBIT__");
+  Ident__USACCUM_FBIT__  = RegisterBuiltinMacro(*this, "__USACCUM_FBIT__");
+  Ident__UACCUM_FBIT__   = RegisterBuiltinMacro(*this, "__UACCUM_FBIT__");
+  Ident__ULACCUM_FBIT__  = RegisterBuiltinMacro(*this, "__ULACCUM_FBIT__");
+
+  // Fractional bits of _Fract types
+  Ident__SFRACT_FBIT__   = RegisterBuiltinMacro(*this, "__SFRACT_FBIT__");
+  Ident__FRACT_FBIT__= RegisterBuiltinMacro(*this, "__FRACT_FBIT__");
+  Ident__LFRACT_FBIT__   = RegisterBuiltinMacro(*this, "__LFRACT_FBIT__");
+  Ident__USFRACT_FBIT__  = RegisterBuiltinMacro(*this, "__USFRACT_FBIT__");
+  Ident__UFRACT_FBIT__   = RegisterBuiltinMacro(*this, "__UFRACT_FBIT__");
+  Ident__ULFRACT_FBIT__  = RegisterBuiltinMacro(*this, "__ULFRACT_FBIT__");
+
+  // Integral bits of _Accum types
+  Ident__SACCUM_IBIT__   = RegisterBuiltinMacro(*this, "__SACCUM_IBIT__");
+  Ident__ACCUM_IBIT__= RegisterBuiltinMacro(*this, "__ACCUM_IBIT__");
+  Ident__LACCUM_IBIT__   = RegisterBuiltinMacro(*this, "__LACCUM_IBIT__");
+  Ident__USACCUM_IBIT__  = RegisterBuiltinMacro(*this, "__USACCUM_IBIT__");
+  Ident__UACCUM_IBIT__   = RegisterBuiltinMacro(*this, "__UACCUM_IBIT__");
+  Ident__ULACCUM_IBIT__  = RegisterBuiltinMacro(*this, "__ULACCUM_IBIT__");
+
   // Microsoft Extensions.
   if (LangOpts.MicrosoftExt) {
 Ident__identifier = RegisterBuiltinMacro(*this, "__identifier");
@@ -1696,6 +1722,68 @@
 // __LINE__ expands to a simple numeric value.
 OS << (PLoc.isValid()? PLoc.getLine() : 1);
 Tok.setKind(tok::numeric_constant);
+
+  // Fixed point macros
+  // Fractional bits of _Accum types
+  } else if (II == Ident__SACCUM_FBIT__) {
+OS << BUILTIN_SACCUM_FBIT;
+Tok.setKind(tok::numeric_constant);
+  } else if (II == Ident__ACCUM_FBIT__) {
+OS << BUILTIN_ACCUM_FBIT;
+Tok.setKind(tok::numeric_constant);
+  } else if (II == Ident_

[PATCH] D46963: [Fixed Point Arithmetic] Test for All Builtin Operations

2018-05-16 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.

This patch includes a test for checking that all supported builtin operations 
can be syntactically declared with fixed point types. Tests for asserting the 
correctness behind each operation will be added in future patches.

This is a child of https://reviews.llvm.org/D46960


Repository:
  rC Clang

https://reviews.llvm.org/D46963

Files:
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGExprScalar.cpp
  test/Frontend/fixed_point_all_builtin_operations.c

Index: test/Frontend/fixed_point_all_builtin_operations.c
===
--- /dev/null
+++ test/Frontend/fixed_point_all_builtin_operations.c
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -Werror %s
+
+// Check that we can use all supported binary and unary operations according to
+// clause 4.1.6 in N1169.
+
+#define ALL_OPERATIONS_FOR_TYPE(TYPE, ID) \
+  TYPE unary_add ## ID (TYPE a)  { return +a; } \
+  TYPE unary_sub ## ID (TYPE a)  { return -a; } \
+  int logical_not ## ID (TYPE a)  { return !a; } \
+  TYPE add ## ID (TYPE a, TYPE b) { return a + b; } \
+  TYPE sub ## ID (TYPE a, TYPE b) { return a - b; } \
+  TYPE mul ## ID (TYPE a, TYPE b) { return a * b; } \
+  TYPE div ## ID (TYPE a, TYPE b) { return a / b; } \
+  TYPE shl ## ID (TYPE a, int b) { return a << b; } \
+  TYPE shr ## ID (TYPE a, int b) { return a >> b; } \
+  TYPE augmented_add ## ID (TYPE a, TYPE b) { a += b; return a; } \
+  TYPE augmented_sub ## ID (TYPE a, TYPE b) { a -= b; return a; } \
+  TYPE augmented_mul ## ID (TYPE a, TYPE b) { a *= b; return a; } \
+  TYPE augmented_div ## ID (TYPE a, TYPE b) { a /= b; return a; } \
+  TYPE augmented_shl ## ID (TYPE a, int b) { a <<= b; return a; } \
+  TYPE augmented_shr ## ID (TYPE a, int b) { a >>= b; return a; } \
+  int eq ## ID (TYPE a, TYPE b) { return a == b; } \
+  int ne ## ID (TYPE a, TYPE b) { return a != b; } \
+  int lt ## ID (TYPE a, TYPE b) { return a < b; } \
+  int le ## ID (TYPE a, TYPE b) { return a <= b; } \
+  int ge ## ID (TYPE a, TYPE b) { return a >= b; } \
+  int gt ## ID (TYPE a, TYPE b) { return a > b; } \
+  TYPE pre_inc ## ID (TYPE a) { return ++a; } \
+  TYPE pre_dec ## ID (TYPE a) { return --a; } \
+  TYPE post_inc ## ID (TYPE a) { return a++; } \
+  TYPE post_dec ## ID (TYPE a) { return a--; } \
+  TYPE deref_pre_inc ## ID (TYPE *a) { return ++(*a); } \
+  TYPE deref_pre_dec ## ID (TYPE *a) { return --(*a); } \
+  TYPE deref_post_inc ## ID (TYPE *a) { return (*a)++; } \
+  TYPE deref_post_dec ## ID (TYPE *a) { return (*a)--; }
+
+#define ALL_OPERATIONS(TYPE, ID) \
+  ALL_OPERATIONS_FOR_TYPE(TYPE, ID) \
+  ALL_OPERATIONS_FOR_TYPE(signed TYPE, Signed ## ID) \
+  ALL_OPERATIONS_FOR_TYPE(unsigned TYPE, Unsigned ## ID) \
+  ALL_OPERATIONS_FOR_TYPE(_Sat TYPE, Sat ## ID) \
+  ALL_OPERATIONS_FOR_TYPE(_Sat signed TYPE, SatSigned ## ID) \
+  ALL_OPERATIONS_FOR_TYPE(_Sat unsigned TYPE, SatUnsigned ## ID)
+
+ALL_OPERATIONS(short _Fract, sf);
+ALL_OPERATIONS(_Fract, f);
+ALL_OPERATIONS(long _Fract, lf);
+ALL_OPERATIONS(short _Accum, sa);
+ALL_OPERATIONS(_Accum, a);
+ALL_OPERATIONS(long _Accum, la);
Index: lib/CodeGen/CGExprScalar.cpp
===
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -2204,17 +2204,29 @@
 const auto *BT = type->getAs();
 switch (BT->getKind()) {
   default: llvm_unreachable("Not a fixed point type!");
+  case BuiltinType::SatShortAccum:
   case BuiltinType::ShortAccum:   fbits = BUILTIN_SACCUM_FBIT; break;
+  case BuiltinType::SatAccum:
   case BuiltinType::Accum:fbits = BUILTIN_ACCUM_FBIT; break;
+  case BuiltinType::SatLongAccum:
   case BuiltinType::LongAccum:fbits = BUILTIN_LACCUM_FBIT; break;
+  case BuiltinType::SatUShortAccum:
   case BuiltinType::UShortAccum:  fbits = BUILTIN_USACCUM_FBIT; break;
+  case BuiltinType::SatUAccum:
   case BuiltinType::UAccum:   fbits = BUILTIN_UACCUM_FBIT; break;
+  case BuiltinType::SatULongAccum:
   case BuiltinType::ULongAccum:   fbits = BUILTIN_ULACCUM_FBIT; break;
+  case BuiltinType::SatShortFract:
   case BuiltinType::ShortFract:   fbits = BUILTIN_SFRACT_FBIT; break;
+  case BuiltinType::SatFract:
   case BuiltinType::Fract:fbits = BUILTIN_FRACT_FBIT; break;
+  case BuiltinType::SatLongFract:
   case BuiltinType::LongFract:fbits = BUILTIN_LFRACT_FBIT; break;
+  case BuiltinType::SatUShortFract:
   case BuiltinType::UShortFract:  fbits = BUILTIN_USFRACT_FBIT; break;
+  case BuiltinType::SatUFract:
   case BuiltinType::UFract:   fbits = BUILTIN_UFRACT_FBIT; break;
+  case BuiltinType::SatULongFract:
   case BuiltinType::ULongFract:   fbits = BUILTIN_ULFRACT_FBIT; break;
 }
 llvm::Value *amt = llvm::ConstantInt::get(value->getType(), 1ULL << fbits,
Index: lib/AST/A

[PATCH] D46963: [Fixed Point Arithmetic] Test for All Builtin Operations

2018-05-16 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147131.

Repository:
  rC Clang

https://reviews.llvm.org/D46963

Files:
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGExprScalar.cpp
  test/Frontend/fixed_point_all_builtin_operations.c

Index: test/Frontend/fixed_point_all_builtin_operations.c
===
--- /dev/null
+++ test/Frontend/fixed_point_all_builtin_operations.c
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -Werror %s
+
+// Check that we can use all supported binary and unary operations according to
+// clause 4.1.6 in N1169.
+
+#define ALL_OPERATIONS_FOR_TYPE(TYPE, ID) \
+  TYPE unary_add ## ID (TYPE a)  { return +a; } \
+  TYPE unary_sub ## ID (TYPE a)  { return -a; } \
+  int logical_not ## ID (TYPE a)  { return !a; } \
+  TYPE add ## ID (TYPE a, TYPE b) { return a + b; } \
+  TYPE sub ## ID (TYPE a, TYPE b) { return a - b; } \
+  TYPE mul ## ID (TYPE a, TYPE b) { return a * b; } \
+  TYPE div ## ID (TYPE a, TYPE b) { return a / b; } \
+  TYPE shl ## ID (TYPE a, int b) { return a << b; } \
+  TYPE shr ## ID (TYPE a, int b) { return a >> b; } \
+  TYPE augmented_add ## ID (TYPE a, TYPE b) { a += b; return a; } \
+  TYPE augmented_sub ## ID (TYPE a, TYPE b) { a -= b; return a; } \
+  TYPE augmented_mul ## ID (TYPE a, TYPE b) { a *= b; return a; } \
+  TYPE augmented_div ## ID (TYPE a, TYPE b) { a /= b; return a; } \
+  TYPE augmented_shl ## ID (TYPE a, int b) { a <<= b; return a; } \
+  TYPE augmented_shr ## ID (TYPE a, int b) { a >>= b; return a; } \
+  int eq ## ID (TYPE a, TYPE b) { return a == b; } \
+  int ne ## ID (TYPE a, TYPE b) { return a != b; } \
+  int lt ## ID (TYPE a, TYPE b) { return a < b; } \
+  int le ## ID (TYPE a, TYPE b) { return a <= b; } \
+  int ge ## ID (TYPE a, TYPE b) { return a >= b; } \
+  int gt ## ID (TYPE a, TYPE b) { return a > b; } \
+  TYPE pre_inc ## ID (TYPE a) { return ++a; } \
+  TYPE pre_dec ## ID (TYPE a) { return --a; } \
+  TYPE post_inc ## ID (TYPE a) { return a++; } \
+  TYPE post_dec ## ID (TYPE a) { return a--; } \
+  TYPE deref_pre_inc ## ID (TYPE *a) { return ++(*a); } \
+  TYPE deref_pre_dec ## ID (TYPE *a) { return --(*a); } \
+  TYPE deref_post_inc ## ID (TYPE *a) { return (*a)++; } \
+  TYPE deref_post_dec ## ID (TYPE *a) { return (*a)--; }
+
+#define ALL_OPERATIONS(TYPE, ID) \
+  ALL_OPERATIONS_FOR_TYPE(TYPE, ID) \
+  ALL_OPERATIONS_FOR_TYPE(signed TYPE, Signed ## ID) \
+  ALL_OPERATIONS_FOR_TYPE(unsigned TYPE, Unsigned ## ID) \
+  ALL_OPERATIONS_FOR_TYPE(_Sat TYPE, Sat ## ID) \
+  ALL_OPERATIONS_FOR_TYPE(_Sat signed TYPE, SatSigned ## ID) \
+  ALL_OPERATIONS_FOR_TYPE(_Sat unsigned TYPE, SatUnsigned ## ID)
+
+ALL_OPERATIONS(short _Fract, ShortFract);
+ALL_OPERATIONS(_Fract, Fract);
+ALL_OPERATIONS(long _Fract, LongFract);
+ALL_OPERATIONS(short _Accum, ShortAccum);
+ALL_OPERATIONS(_Accum, Accum);
+ALL_OPERATIONS(long _Accum, LongAccum);
Index: lib/CodeGen/CGExprScalar.cpp
===
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -2204,17 +2204,29 @@
 const auto *BT = type->getAs();
 switch (BT->getKind()) {
   default: llvm_unreachable("Not a fixed point type!");
+  case BuiltinType::SatShortAccum:
   case BuiltinType::ShortAccum:   fbits = BUILTIN_SACCUM_FBIT; break;
+  case BuiltinType::SatAccum:
   case BuiltinType::Accum:fbits = BUILTIN_ACCUM_FBIT; break;
+  case BuiltinType::SatLongAccum:
   case BuiltinType::LongAccum:fbits = BUILTIN_LACCUM_FBIT; break;
+  case BuiltinType::SatUShortAccum:
   case BuiltinType::UShortAccum:  fbits = BUILTIN_USACCUM_FBIT; break;
+  case BuiltinType::SatUAccum:
   case BuiltinType::UAccum:   fbits = BUILTIN_UACCUM_FBIT; break;
+  case BuiltinType::SatULongAccum:
   case BuiltinType::ULongAccum:   fbits = BUILTIN_ULACCUM_FBIT; break;
+  case BuiltinType::SatShortFract:
   case BuiltinType::ShortFract:   fbits = BUILTIN_SFRACT_FBIT; break;
+  case BuiltinType::SatFract:
   case BuiltinType::Fract:fbits = BUILTIN_FRACT_FBIT; break;
+  case BuiltinType::SatLongFract:
   case BuiltinType::LongFract:fbits = BUILTIN_LFRACT_FBIT; break;
+  case BuiltinType::SatUShortFract:
   case BuiltinType::UShortFract:  fbits = BUILTIN_USFRACT_FBIT; break;
+  case BuiltinType::SatUFract:
   case BuiltinType::UFract:   fbits = BUILTIN_UFRACT_FBIT; break;
+  case BuiltinType::SatULongFract:
   case BuiltinType::ULongFract:   fbits = BUILTIN_ULFRACT_FBIT; break;
 }
 llvm::Value *amt = llvm::ConstantInt::get(value->getType(), 1ULL << fbits,
Index: lib/AST/ASTContext.cpp
===
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -1797,6 +1797,10 @@
 case BuiltinType::UShortAccum:
 case BuiltinType::ShortFract:
 case BuiltinType::UShortFract:
+case BuiltinType::SatShortAccum:
+case BuiltinTy

[PATCH] D46979: [Fixed Point Arithmetic] Test for Conversion Between Valid Builtin Types

2018-05-16 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.

This patch contains changes and a test for checking that fixed point types can 
be converted between all other valid types. Fixed point types can be converted 
between floating point types, integral types, and other fixed point types.

This is a child of https://reviews.llvm.org/D46963


Repository:
  rC Clang

https://reviews.llvm.org/D46979

Files:
  include/clang/AST/OperationKinds.def
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Sema/SemaExpr.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point_all_conversions.c

Index: test/Frontend/fixed_point_all_conversions.c
===
--- /dev/null
+++ test/Frontend/fixed_point_all_conversions.c
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -Werror %s
+
+// Test for conversions between fixed point types and all other valid types.
+
+// Conversion from one type to another type
+#define CONVERT(FROM_TYPE, FROM_ID, TO_TYPE, TO_ID) \
+  TO_TYPE FROM_ID ## _to_ ## TO_ID (FROM_TYPE x) { return x; }
+
+// Conversion between 2 types
+#define CONVERT_COMBINATION(TYPE1, ID1, TYPE2, ID2) \
+  CONVERT(TYPE1, ID1, TYPE2, ID2) \
+  CONVERT(TYPE2, ID2, TYPE1, ID1)
+
+// Conversion between one type and floating point types
+#define CONVERT_BETWEEN_FLOATS(TYPE, ID) \
+  CONVERT_COMBINATION(TYPE, ID, float, Float) \
+  CONVERT_COMBINATION(TYPE, ID, double, Double)
+
+// Conversion between one type and an integral type with differant signage
+#define CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, INT_TYPE, INT_ID) \
+  CONVERT_COMBINATION(TYPE, ID, INT_TYPE, INT_ID) \
+  CONVERT_COMBINATION(TYPE, ID, signed INT_TYPE, Signed ## INT_ID) \
+  CONVERT_COMBINATION(TYPE, ID, unsigned INT_TYPE, Unsigned ## INT_ID)
+
+// Conversion between one type and all integral types
+#define CONVERT_BETWEEN_INTEGRALS(TYPE, ID) \
+  CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, char, Char) \
+  CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, short, Short) \
+  CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, int, Int) \
+  CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, long, Long) \
+  CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, long long, LongLong)
+
+// Conversion between one type and a fixed point type with different saturation
+#define CONVERT_BETWEEN_FIXED_POINT_WITH_SAT(TYPE, ID, FIXED_TYPE, FIXED_ID) \
+  CONVERT_COMBINATION(TYPE, ID, FIXED_TYPE, FIXED_ID) \
+  CONVERT_COMBINATION(TYPE, ID, _Sat FIXED_TYPE, Sat ## FIXED_ID)
+
+// Conversion between one type and a fixed point type with different signage
+#define CONVERT_BETWEEN_FIXED_POINT_WITH_SIGN(TYPE, ID, FIXED_TYPE, FIXED_ID) \
+  CONVERT_BETWEEN_FIXED_POINT_WITH_SAT(TYPE, ID, FIXED_TYPE, FIXED_ID) \
+  CONVERT_BETWEEN_FIXED_POINT_WITH_SAT(TYPE, ID, signed FIXED_TYPE, Signed ## FIXED_ID) \
+  CONVERT_BETWEEN_FIXED_POINT_WITH_SAT(TYPE, ID, unsigned FIXED_TYPE, Unsigned ## FIXED_ID)
+
+// Convert between one type and all fixed point types.
+// Add "Type" to the end of the ID to avoid multiple definitions of a function
+// if the Type is a fixed point type.
+#define CONVERT_BETWEEN_FIXED_POINT(TYPE, ID) \
+  CONVERT_BETWEEN_FIXED_POINT_WITH_SIGN(TYPE, ID, _Fract, FractType) \
+  CONVERT_BETWEEN_FIXED_POINT_WITH_SIGN(TYPE, ID, _Accum, AccumType)
+
+// Convert between one type and all other types
+#define CONVERT_BETWEEN_ALL_TYPES(TYPE, ID) \
+  CONVERT_BETWEEN_FLOATS(TYPE, ID) \
+  CONVERT_BETWEEN_INTEGRALS(TYPE, ID) \
+  CONVERT_BETWEEN_FIXED_POINT(TYPE, ID)
+
+#define CONVERT_FIXED_POINT_TYPE_WITH_SAT(TYPE, ID) \
+  CONVERT_BETWEEN_ALL_TYPES(TYPE, ID) \
+  CONVERT_BETWEEN_ALL_TYPES(_Sat TYPE, Sat ## ID)
+
+#define CONVERT_FIXED_POINT_TYPE(TYPE, ID) \
+  CONVERT_FIXED_POINT_TYPE_WITH_SAT(TYPE, ID) \
+  CONVERT_FIXED_POINT_TYPE_WITH_SAT(signed TYPE, Signed ## ID) \
+  CONVERT_FIXED_POINT_TYPE_WITH_SAT(unsigned TYPE, Unsigned ## ID)
+
+CONVERT_FIXED_POINT_TYPE(short _Fract, ShortFract);
+CONVERT_FIXED_POINT_TYPE(_Fract, Fract);
+CONVERT_FIXED_POINT_TYPE(long _Fract, LongFract);
+
+CONVERT_FIXED_POINT_TYPE(short _Accum, ShortAccum);
+CONVERT_FIXED_POINT_TYPE(_Accum, Accum);
+CONVERT_FIXED_POINT_TYPE(long _Accum, LongAccum);
Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp
===
--- lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -321,6 +321,7 @@
 const LocationContext *LCtx = Pred->getLocationContext();
 
 switch (CastE->getCastKind()) {
+  case CK_FloatingToFixedPoint: llvm_unreachable("CK_FloatingToFixedPoint");
   case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating");
   case CK_IntegralToFixedPoint

[PATCH] D46986: [Fixed Point Arithmetic] Validation Test for Fixed Point Binary Operations and Saturated Addition

2018-05-16 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.

This patch contains tests for validating the logic behind each builtin 
operation on fixed point types and tests on addition between saturated _Fract 
types.

- More macros wer added to the FixedPoint.h header on the min and max values 
for each type which will be required for operations on saturated types.
- Updated the logic when converting between fixed point types to take into 
account saturation. Fixed point type conversions do not fall under the "usual 
arithmetic conversions" where the resulting type on a binary operation 
resulting in a fixed point type does not need to be the type of either operands.
- Rounded down _Fract literals of 1 (1.0hr, 1.0r, 1.0lr) to the respective 
maximum values for each _Fract type.

This is a child of https://reviews.llvm.org/D46979


Repository:
  rC Clang

https://reviews.llvm.org/D46986

Files:
  include/clang/AST/Type.h
  include/clang/Basic/FixedPoint.h.in
  lib/AST/Type.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Sema/SemaExpr.cpp
  test/Frontend/fixed_point_all_builtin_operations.c

Index: test/Frontend/fixed_point_all_builtin_operations.c
===
--- test/Frontend/fixed_point_all_builtin_operations.c
+++ test/Frontend/fixed_point_all_builtin_operations.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -Werror %s
+// RUN: %clang_cc1 -Werror  -S -emit-llvm %s -o - | lli
 
 // Check that we can use all supported binary and unary operations according to
 // clause 4.1.6 in N1169.
@@ -48,3 +48,59 @@
 ALL_OPERATIONS(short _Accum, ShortAccum);
 ALL_OPERATIONS(_Accum, Accum);
 ALL_OPERATIONS(long _Accum, LongAccum);
+
+#define ASSERT(x) if (!(x)) return 1;
+
+#define BINARY_OPS_FOR_TYPE(TYPE, ID, SUFFIX) \
+  { \
+TYPE a = 0.5 ## SUFFIX; \
+TYPE b = 0.25 ## SUFFIX; \
+ASSERT(add ## ID(a, b) == 0.75 ## SUFFIX); \
+ASSERT(sub ## ID(a, b) == 0.25 ## SUFFIX); \
+ASSERT(mul ## ID(a, b) == 0.125 ## SUFFIX); \
+ASSERT(div ## ID(b, a) == 0.5 ## SUFFIX); \
+ASSERT(shl ## ID(b, 1) == a); \
+ASSERT(shr ## ID(a, 1) == b); \
+ASSERT(lt  ## ID(b, a)); \
+ASSERT(le  ## ID(b, a)); \
+ASSERT(gt  ## ID(a, b)); \
+ASSERT(ge  ## ID(a, b)); \
+ASSERT(eq  ## ID(a, b) == 0); \
+ASSERT(ne  ## ID(a, b)); \
+ASSERT(augmented_add ## ID(a, b) == 0.75 ## SUFFIX); \
+ASSERT(augmented_sub ## ID(a, b) == 0.25 ## SUFFIX); \
+ASSERT(augmented_mul ## ID(a, b) == 0.125 ## SUFFIX); \
+ASSERT(augmented_div ## ID(b, a) == 0.5 ## SUFFIX); \
+ASSERT(augmented_shl ## ID(b, 1) == a); \
+ASSERT(augmented_shr ## ID(a, 1) == b); \
+  }
+
+#define BINARY_OPS(TYPE, ID, SUFFIX) \
+  BINARY_OPS_FOR_TYPE(TYPE, ID, SUFFIX); \
+  BINARY_OPS_FOR_TYPE(signed TYPE, Signed ## ID, SUFFIX); \
+  BINARY_OPS_FOR_TYPE(unsigned TYPE, Unsigned ## ID, u ## SUFFIX); \
+  BINARY_OPS_FOR_TYPE(_Sat TYPE, Sat ## ID, SUFFIX); \
+  BINARY_OPS_FOR_TYPE(_Sat signed TYPE, SatSigned ## ID, SUFFIX); \
+  BINARY_OPS_FOR_TYPE(_Sat unsigned TYPE, SatUnsigned ## ID, u ## SUFFIX);
+
+#define FRACT_SAT_BINARY_OPS(TYPE, ID, SUFFIX) \
+  { \
+TYPE a = 0.7 ## SUFFIX; \
+TYPE b = 0.9 ## SUFFIX; \
+ASSERT(add ## ID(a, b) == 1.0 ## SUFFIX); \
+  }
+
+int main(){
+  BINARY_OPS(short _Fract, ShortFract, hr);
+  BINARY_OPS(_Fract, Fract, r);
+  BINARY_OPS(long _Fract, LongFract, lr);
+  BINARY_OPS(short _Accum, ShortAccum, hk);
+  BINARY_OPS(_Accum, Accum, k);
+  BINARY_OPS(long _Accum, LongAccum, lk);
+
+  FRACT_SAT_BINARY_OPS(_Sat short _Fract, SatShortFract, hr);
+  FRACT_SAT_BINARY_OPS(_Sat _Fract, SatFract, r);
+  FRACT_SAT_BINARY_OPS(_Sat long _Fract, SatLongFract, lr);
+
+  return 0;
+}
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -1254,8 +1254,12 @@
   return FixedPointTy;
 }
 
-/// \brief Handle arithmethic conversion with fixed point types.  Helper
-/// function of UsualArithmeticConversions().
+/// \brief Handle arithmethic conversion with fixed point types. The usual
+/// arithmetic conversions do not apply to fixed point type conversions between
+/// integers or other fixed point types due to potential loss of precision.
+/// For this case of fixed point types, the resulting type in a binary operation
+/// does not need to be exactly one of the 2 operand types.
+/// Implemented according to Clause 6.3.1.8 of ISO/IEC JTC1 SC22 WG14 N1169.
 static QualType handleFixedPointConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
QualType RHSType,
@@ -1267,30 +1271,25 @@
   bool RHSFixed = RHSType->isFixedPointType();
 
   if (LHSFixed && RHSFixed) {
-// Cast up the smaller operand to the bigger
+bool LHSSigned = LHSType->isSignedFixedPointType();
+bool RHSSigned = R

[PATCH] D46987: [Fixed Point Arithmetic] Validation Test for Saturated Subtraction on Signed _Fracts

2018-05-16 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.

This patch includes the logic for subtraction on saturated _Fract types and a 
test for thm.

- Also fixed incorrect minimum value for each _Fract type
- Getters for each fixed point min and max value for a given type
- Correction when casting from a fixed point to a float. If the fixed point 
data and sign bits do not take up the whole width of the integer (ie. has 
padding), we will need to either zero out the padding or extend the sign into 
the padding if it is negative to ensure the correct floating point value is 
produced after casting.

This is a child of https://reviews.llvm.org/D46986


Repository:
  rC Clang

https://reviews.llvm.org/D46987

Files:
  include/clang/AST/Type.h
  include/clang/Basic/FixedPoint.h.in
  lib/AST/Type.cpp
  lib/CodeGen/CGExprScalar.cpp
  test/Frontend/fixed_point_all_builtin_operations.c

Index: test/Frontend/fixed_point_all_builtin_operations.c
===
--- test/Frontend/fixed_point_all_builtin_operations.c
+++ test/Frontend/fixed_point_all_builtin_operations.c
@@ -88,6 +88,15 @@
 TYPE a = 0.7 ## SUFFIX; \
 TYPE b = 0.9 ## SUFFIX; \
 ASSERT(add ## ID(a, b) == 1.0 ## SUFFIX); \
+a = -0.7 ## SUFFIX; \
+b = -0.9 ## SUFFIX; \
+ASSERT(add ## ID(a, b) == -0.5 ## SUFFIX - 0.5 ## SUFFIX); \
+a = 0.7 ## SUFFIX; \
+b = -0.9 ## SUFFIX; \
+ASSERT(sub ## ID(a, b) == 1.0 ## SUFFIX); \
+a = -0.7 ## SUFFIX; \
+b = 0.9 ## SUFFIX; \
+ASSERT(sub ## ID(a, b) == -0.5 ## SUFFIX - 0.5 ## SUFFIX); \
   }
 
 int main(){
Index: lib/CodeGen/CGExprScalar.cpp
===
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -806,6 +806,11 @@
   }
   Value *VisitAsTypeExpr(AsTypeExpr *CE);
   Value *VisitAtomicExpr(AtomicExpr *AE);
+
+  // For all fixed point values, we usually do not care about the padding bits,
+  // but if we convert to another type dependent on the whole value of the
+  // underlying type, we will need to either zero extend or sign extend.
+  llvm::Value* FixedPointExtendSignToPadding(const QualType& Ty, llvm::Value* Val);
 };
 }  // end anonymous namespace.
 
@@ -1675,6 +1680,41 @@
   return true;
 }
 
+// For all fixed point values, we usually do not care about the padding bits,
+// but if we convert to another type dependent on the whole value of the
+// underlying type, we will need to either zero extend or sign extend.
+llvm::Value* ScalarExprEmitter::FixedPointExtendSignToPadding(const QualType& Ty,
+  llvm::Value* Val) {
+  assert(Ty->isFixedPointType());
+
+  llvm::Type *opTy = CGF.CGM.getTypes().ConvertType(Ty);
+  unsigned BitWidth = opTy->getIntegerBitWidth();
+  unsigned fbits = getFixedPointFBits(Ty);
+  unsigned ibits = getFixedPointIBits(Ty);
+
+  if (Ty->isSignedFixedPointType()) {
+assert((BitWidth >= fbits + ibits + 1) &&
+   "Cannot fit signed fixed point bits into integral type");
+
+unsigned ShiftBits = BitWidth - (fbits + ibits + 1);
+if (!ShiftBits) {
+  return Val;
+}
+
+return Builder.CreateAShr(Builder.CreateShl(Val, ShiftBits), ShiftBits);
+  } else {
+assert((BitWidth >= fbits + ibits) &&
+   "Cannot fit unsigned fixed point bits into integral type");
+
+unsigned ShiftBits = BitWidth - (fbits + ibits);
+if (!ShiftBits) {
+  return Val;
+}
+
+return Builder.CreateLShr(Builder.CreateShl(Val, ShiftBits), ShiftBits);
+  }
+}
+
 // VisitCastExpr - Emit code for an explicit or implicit cast.  Implicit casts
 // have to handle a more broad range of conversions than explicit casts, as they
 // handle things like function to ptr-to-function decay etc.
@@ -1894,8 +1934,12 @@
 assert(DestTy->isFloatingType());
 assert(E->getType()->isFixedPointType());
 unsigned fbits = getFixedPointFBits(E->getType());
-return Builder.CreateFDiv(EmitScalarConversion(Visit(E), E->getType(), DestTy, CE->getExprLoc()),
-  llvm::ConstantFP::get(CGF.CGM.FloatTy, (1ULL << fbits) * 1.0));
+
+llvm::Value *Val = FixedPointExtendSignToPadding(E->getType(), Visit(E));
+Val = EmitScalarConversion(Val, E->getType(), DestTy, CE->getExprLoc());
+
+return Builder.CreateFDiv(
+Val, llvm::ConstantFP::get(CGF.CGM.FloatTy, (1ULL << fbits) * 1.0));
   }
 
   case CK_IntegralCast:
@@ -3104,61 +3148,10 @@
 assert(op.LHS->getType() == op.RHS->getType());
 assert(op.LHS->getType() == opTy);
 
-llvm::Value *SatMaxVal;
-llvm::Value *SatMinVal;
-
-const auto &BT = op.Ty->getAs();
-switch (BT->getKind()) {
-  default: llvm_unreachable("Unhandled saturated signed fixed point type");
-  case BuiltinType::SatShortAccum:
- SatMaxVal = llvm::ConstantInt::get(opTy, SACCUM_MAX_AS_INT

[PATCH] D46990: [Fixed Point Arithmetic] Validation Test for Saturated Multiplication

2018-05-16 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.

This patch contains changes for multiplication on saturated _Fract types.

Since we already upcast the underlying integer for the fixed point type, we can 
do a simple check to see if the resulting value is larger or smaller than the 
max or min for the fixed point types.

This is a child of https://reviews.llvm.org/D46987


Repository:
  rC Clang

https://reviews.llvm.org/D46990

Files:
  lib/CodeGen/CGExprScalar.cpp
  test/Frontend/fixed_point_all_builtin_operations.c

Index: test/Frontend/fixed_point_all_builtin_operations.c
===
--- test/Frontend/fixed_point_all_builtin_operations.c
+++ test/Frontend/fixed_point_all_builtin_operations.c
@@ -97,6 +97,8 @@
 a = -0.7 ## SUFFIX; \
 b = 0.9 ## SUFFIX; \
 ASSERT(sub ## ID(a, b) == -0.5 ## SUFFIX - 0.5 ## SUFFIX); \
+a = -0.5 ## SUFFIX - 0.5 ## SUFFIX; \
+ASSERT(mul ## ID(a, a) == 1.0 ## SUFFIX); \
   }
 
 int main(){
Index: lib/CodeGen/CGExprScalar.cpp
===
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -690,11 +690,84 @@
 bufferWidth = 128;
   }
 
-  LHSVal = Builder.CreateIntCast(LHSVal, Builder.getIntNTy(bufferWidth), isSignedResult);
-  RHSVal = Builder.CreateIntCast(RHSVal, Builder.getIntNTy(bufferWidth), isSignedResult);
+  llvm::Type *ResultTy = Builder.getIntNTy(bufferWidth);
+  LHSVal = Builder.CreateIntCast(LHSVal, ResultTy, isSignedResult);
+  RHSVal = Builder.CreateIntCast(RHSVal, ResultTy, isSignedResult);
 
   llvm::Value* MulResult = Builder.CreateMul(LHSVal, RHSVal);
   MulResult = Builder.CreateAShr(MulResult, getFixedPointFBits(Ops.Ty));
+
+  // At this point, MulResult has not been truncated yet and still has extra
+  // assigned bits we can use to check for magnitude overflows.
+  if (Ops.Ty->isSaturatedFixedPointType()) {
+llvm::Value *SatMaxVal = llvm::ConstantInt::get(
+ResultTy, getFixedPointMaxVal(Ops.Ty));
+llvm::Value *SatMinVal = llvm::ConstantInt::get(
+ResultTy, getFixedPointMinVal(Ops.Ty));
+
+unsigned FixedPointBits;
+if (Ops.Ty->isSignedFixedPointType()) {
+  FixedPointBits = getFixedPointIBits(Ops.Ty) + getFixedPointFBits(Ops.Ty) + 1;
+} else {
+  FixedPointBits = getFixedPointIBits(Ops.Ty) + getFixedPointFBits(Ops.Ty);
+}
+unsigned MSBBitShift = FixedPointBits - 1;
+
+// Number of data + sign bits used in multiplication result after
+// shifting but before truncation.
+unsigned UntruncatedBitWidth = FixedPointBits * 2;
+unsigned BitMask = (1 << UntruncatedBitWidth) - 1;
+llvm::Value *MaskedMulResult = Builder.CreateAnd(MulResult, BitMask);
+
+if (Ops.Ty->isSignedFixedPointType()) {
+  if (Ops.Ty->isAccumFixedPointType()) {
+llvm::Type *Int1Ty = llvm::Type::getInt1Ty(Ops.LHS->getContext());
+llvm::Value *LHSMSB = Builder.CreateIntCast(Builder.CreateLShr(Ops.LHS, MSBBitShift),
+Int1Ty, /*isSigned=*/true);
+llvm::Value *RHSMSB = Builder.CreateIntCast(Builder.CreateLShr(Ops.RHS, MSBBitShift),
+Int1Ty, /*isSigned=*/true);
+
+// Cap at max if both operand signs were the same and the result is greater than the
+// max possible value.
+llvm::Value *UseSatMax = Builder.CreateAnd(
+Builder.CreateICmpEQ(LHSMSB, RHSMSB),
+Builder.CreateICmpUGT(MaskedMulResult, SatMaxVal));
+
+// Cap at min if the operands were different, and the unsigned
+// respresentation of the result is greater than the maximum possible
+// unsigned value that can be represented with the resulting fixed
+// point bits. Don't use SatMaxVal here since it represents the max
+// for an signed value.
+llvm::Value *UseSatMin = Builder.CreateAnd(
+Builder.CreateXor(LHSMSB, RHSMSB),
+Builder.CreateICmpUGT(MaskedMulResult, llvm::ConstantInt::get(ResultTy, BitMask)));
+
+MulResult = Builder.CreateSelect(
+UseSatMax, SatMaxVal, Builder.CreateSelect(UseSatMin, SatMinVal, MulResult));
+  } else {
+// The only situation a _Fract overflows is if both are signed and
+// equal to -1. Signed multiplication would yield a result of -1 when
+// the result should be 1. Instead return the max possible value.
+assert(Ops.Ty->isFractFixedPointType());
+
+unsigned FractMask = (1ULL << FixedPointBits) - 1;
+llvm::Value *MaskedLHSVal = Builder.CreateAnd(LHSVal, FractMask, "Mask

[PATCH] D47016: [Fixed Point Arithmetic] Validation Test for Saturated Division and Comparison Fix

2018-05-17 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.

This patch includes changes for division on saturated fixed point types. 
Overflow occurs when the resulting value cannot fit into the number of data 
bits for the resulting type.

For signed division, we cap at the max value of the type when the dividend sign 
is positive, divisor sign is negative, but the quotient is still positive. 
Reciprocally, we cap at the min value if the dividend is negative, divisor is 
positive, and quotient is negative.

For unsigned division, overflow occurs if the resulting value exceeds the max 
possible value that this type can hold.

The logic for comparisons between fixed point types was also fixed to account 
for padding bits. Since the padding bits contains values we do not care about, 
we mask the fixed point data bits in the underlying integral that we do care 
about and compare them.

This is a child of https://reviews.llvm.org/D46990


Repository:
  rC Clang

https://reviews.llvm.org/D47016

Files:
  include/clang/AST/Type.h
  include/clang/Basic/FixedPoint.h.in
  lib/AST/Type.cpp
  lib/CodeGen/CGExprScalar.cpp
  test/Frontend/fixed_point_all_builtin_operations.c
  test/Frontend/fixed_point_validation.c

Index: test/Frontend/fixed_point_validation.c
===
--- test/Frontend/fixed_point_validation.c
+++ test/Frontend/fixed_point_validation.c
@@ -57,7 +57,7 @@
 
   s_accum = s_accum2;
   // CHECK:  {{.*}} = load i16, i16* %s_accum2, align 2
-  // CHECK-NEXT: store i16 %1, i16* %s_accum, align 2
+  // CHECK-NEXT: store i16 {{.*}}, i16* %s_accum, align 2
 
   assert(s_accum == s_accum2);
   // CHECK:  {{.*}} = load i16, i16* %s_accum, align 2
@@ -114,9 +114,13 @@
   // CHECK:  {{.*}} = icmp sgt i16 {{.*}}, {{.*}}
 
   assert(s_fract2 < s_fract);
-  // CHECK:  {{.*}} = load i16, i16* %s_fract2, align 2
-  // CHECK-NEXT: {{.*}} = load i16, i16* %s_fract, align 2
-  // CHECK-NEXT: {{.*}} = icmp slt i16 {{.*}}, {{.*}}
+  // CHECK:  [[VAL:%.+]] = load i16, i16* %s_fract2, align 2
+  // CHECK-NEXT: [[VAL2:%.+]] = load i16, i16* %s_fract, align 2
+  // CHECK-NEXT: [[SHIFTED_VAL:%.+]] = shl i16 [[VAL]], 8
+  // CHECK-NEXT: [[CORRECTED_VAL:%.+]] = ashr i16 [[SHIFTED_VAL]], 8
+  // CHECK-NEXT: [[SHIFTED_VAL2:%.+]] = shl i16 [[VAL2]], 8
+  // CHECK-NEXT: [[CORRECTED_VAL2:%.+]] = ashr i16 [[SHIFTED_VAL2]], 8
+  // CHECK-NEXT: {{.*}} = icmp slt i16 [[CORRECTED_VAL]], [[CORRECTED_VAL2]]
 
   assert(s_fract >= s_fract);
   // CHECK:  {{.*}} = icmp sge i16 {{.*}}, {{.*}}
Index: test/Frontend/fixed_point_all_builtin_operations.c
===
--- test/Frontend/fixed_point_all_builtin_operations.c
+++ test/Frontend/fixed_point_all_builtin_operations.c
@@ -99,6 +99,12 @@
 ASSERT(sub ## ID(a, b) == -0.5 ## SUFFIX - 0.5 ## SUFFIX); \
 a = -0.5 ## SUFFIX - 0.5 ## SUFFIX; \
 ASSERT(mul ## ID(a, a) == 1.0 ## SUFFIX); \
+a = 0.8 ## SUFFIX; \
+b = 0.5 ## SUFFIX; \
+ASSERT(a / b == 1.0 ## SUFFIX); \
+a = -0.8 ## SUFFIX; \
+b = 0.5 ## SUFFIX; \
+ASSERT(a / b == -0.5 ## SUFFIX - 0.5 ## SUFFIX); \
   }
 
 int main(){
Index: lib/CodeGen/CGExprScalar.cpp
===
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -2837,6 +2837,14 @@
 assert(LHSTy == RHSTy);
 
 bool isSignedResult = LHSTy->isSignedFixedPointType() || RHSTy->isSignedFixedPointType();
+unsigned fbits = getFixedPointFBits(Ops.Ty);
+unsigned ibits = getFixedPointIBits(Ops.Ty);
+unsigned FixedPointBits;
+if (isSignedResult) {
+  FixedPointBits = fbits + ibits + 1;
+} else {
+  FixedPointBits = fbits + ibits;
+}
 
 // Round up the bit widths to allocate enough space for calculating the
 // result.
@@ -2848,9 +2856,85 @@
 
 LHSVal = Builder.CreateIntCast(LHSVal, Builder.getIntNTy(bufferWidth), isSignedResult);
 RHSVal = Builder.CreateIntCast(RHSVal, Builder.getIntNTy(bufferWidth), isSignedResult);
-LHSVal = Builder.CreateShl(LHSVal, getFixedPointFBits(LHSTy));
 
+LHSVal = Builder.CreateShl(LHSVal, fbits);
 llvm::Value* DivResult = Builder.CreateSDiv(LHSVal, RHSVal);
+
+if (Ops.Ty->isSaturatedFixedPointType()) {
+  llvm::Value *SatMaxVal = llvm::ConstantInt::get(
+  DivResult->getType(), getFixedPointMaxVal(Ops.Ty));
+  llvm::Value *SatMinVal = llvm::ConstantInt::get(
+  DivResult->getType(), getFixedPointMinVal(Ops.Ty));
+
+  unsigned FixedPointBits;
+  if (Ops.Ty->isSignedFixedPointType()) {
+FixedPointBits = getFixedPointIBits(Ops.Ty) + getFixedPointFBits(Ops.Ty) + 1;
+  } else {
+FixedPointBits = getFixedPointIBits(Ops.Ty) + getFixedPointFBits(Ops.Ty);
+  }
+  unsigned MSBBitShift = FixedPointBits - 1;
+
+  // Number of data + s

[PATCH] D47017: [Fixed Point Arithmetic] Validation Test for Saturated Shift Left, Saturated Unsigned _Fract Types, and Fix for Saturated Unsigned Addition

2018-05-17 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.

This patch includes changes for the shift left operator involving saturated 
fixed point types.

For unsigned shifting, overflow occurs if the number of bits we shift exceeds 
the number of leading zeros in the number. This number is found using the 
intrinsic llvm function `ctlz`.

For signed shifting, if the number is positive, we cap at the max value for 
that type if the number of bits we shift exceeds the number of leading zeros. 
If the number is negative, we cap at the min value for that type if the number 
of bits we shift exceeds the number of leading ones. `ctlz` can be used in this 
case after flipping the bits in the number.

- Saturation tests were also added for saturated unsigned _Fract types.
- Added a fix to unsigned addition for saturated fixed point types where we 
would not be able to get the overflow if the number of data bits was equal to 
the underlying integer width. In this case, we need to use the intrinsic 
function `uadd.with.overflow` to detect overflow on this carry bit.

This is a child of https://reviews.llvm.org/D47016


Repository:
  rC Clang

https://reviews.llvm.org/D47017

Files:
  include/clang/AST/Type.h
  lib/CodeGen/CGExprScalar.cpp
  test/Frontend/fixed_point_all_builtin_operations.c

Index: test/Frontend/fixed_point_all_builtin_operations.c
===
--- test/Frontend/fixed_point_all_builtin_operations.c
+++ test/Frontend/fixed_point_all_builtin_operations.c
@@ -105,6 +105,20 @@
 a = -0.8 ## SUFFIX; \
 b = 0.5 ## SUFFIX; \
 ASSERT(a / b == -0.5 ## SUFFIX - 0.5 ## SUFFIX); \
+a = 0.1 ## SUFFIX; \
+ASSERT(a << 4 == 1.0 ## SUFFIX); \
+a = -0.8 ## SUFFIX; \
+ASSERT(a << 4 == -0.5 ## SUFFIX - 0.5 ## SUFFIX); \
+  }
+
+#define FRACT_SATU_BINARY_OPS(TYPE, ID, SUFFIX) \
+  { \
+TYPE a = 0.7 ## SUFFIX; \
+TYPE b = 0.9 ## SUFFIX; \
+ASSERT(a + b == 1.0 ## SUFFIX); \
+ASSERT(a - b == 0.0 ## SUFFIX); \
+ASSERT(b / a == 1.0 ## SUFFIX); \
+ASSERT(a << 1 == 1.0 ## SUFFIX); \
   }
 
 int main(){
@@ -119,5 +133,9 @@
   FRACT_SAT_BINARY_OPS(_Sat _Fract, SatFract, r);
   FRACT_SAT_BINARY_OPS(_Sat long _Fract, SatLongFract, lr);
 
+  FRACT_SATU_BINARY_OPS(_Sat unsigned short _Fract, SatUnsignedShortFract, uhr);
+  FRACT_SATU_BINARY_OPS(_Sat unsigned _Fract, SatUnsignedFract, ur);
+  FRACT_SATU_BINARY_OPS(_Sat unsigned long _Fract, SatUnsignedLongFract, ulr);
+
   return 0;
 }
Index: lib/CodeGen/CGExprScalar.cpp
===
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -1144,7 +1144,9 @@
   }
 
   // Ignore conversions like int -> uint.
-  if (SrcTy == DstTy)
+  // Except for fixed point types which may need radix transformations.
+  bool WorkingOnFixedPoints = DstType->isFixedPointType() && SrcType->isFixedPointType();
+  if (SrcTy == DstTy && !WorkingOnFixedPoints)
 return Src;
 
   // Handle pointer conversions next: pointers can only be converted to/from
@@ -1248,7 +1250,6 @@
 DstTy = CGF.FloatTy;
   }
 
-  bool WorkingOnFixedPoints = DstType->isFixedPointType() && SrcType->isFixedPointType();
   int order = WorkingOnFixedPoints ? CGF.getContext().getFixedPointTypeOrder(DstType, SrcType) : 0;
 
   if (WorkingOnFixedPoints && order < 0) {
@@ -2876,7 +2877,7 @@
 
   // Number of data + sign bits used in division
   unsigned DividendBits = FixedPointBits + fbits;
-  unsigned BitMask = (1 << DividendBits) - 1;
+  uint64_t BitMask = (static_cast<__int128_t>(1ULL) << DividendBits) - 1;
   llvm::Value *MaskedDivResult = Builder.CreateAnd(DivResult, BitMask);
 
   if (Ops.Ty->isSignedFixedPointType()) {
@@ -3310,19 +3311,19 @@
 llvm::Value *SatMinVal = llvm::ConstantInt::get(
 opTy, getFixedPointMinVal(op.Ty));
 
-unsigned MSBBitShift;
 if (op.Ty->isSignedFixedPointType()) {
-  MSBBitShift = getFixedPointIBits(op.Ty) + getFixedPointFBits(op.Ty);
-} else {
-  MSBBitShift = getFixedPointIBits(op.Ty) + getFixedPointFBits(op.Ty) - 1;
-}
+  unsigned MSBBitShift;
+  if (op.Ty->isSignedFixedPointType()) {
+MSBBitShift = getFixedPointIBits(op.Ty) + getFixedPointFBits(op.Ty);
+  } else {
+MSBBitShift = getFixedPointIBits(op.Ty) + getFixedPointFBits(op.Ty) - 1;
+  }
 
-llvm::Value *Sum = Builder.CreateAdd(op.LHS, op.RHS);
-llvm::Value *LHSMSB = Builder.CreateLShr(op.LHS, MSBBitShift);
-llvm::Value *RHSMSB = Builder.CreateLShr(op.RHS, MSBBitShift);
-llvm::Value *ResultMSB = Builder.CreateLShr(Sum, MSBBitShift);
+  llvm::Value *Sum = Builder.CreateAdd(op.LHS, op.RHS);
+  llvm::Value *LHSMSB = Builder.CreateLShr(op.LHS, MSBBitShift);
+  llvm::Value *RHSMSB = Builder.CreateLShr(op.RHS, MSBBitShift);
+  llvm::Value *ResultMSB = Builder.CreateLShr(Sum, MSBBit

[PATCH] D47030: [Fixed Point Arithmetic] Checks for Precision Macros

2018-05-17 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.
Herald added a subscriber: mgorny.

This patch includes checks that the precision macros used for the fixed point 
fractional and integral bits meet the requirements for clause 6.2.6.3 in 
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf.

Checks for any disagreements with the recommendations will throw warnings.

I also added my own warning that recommends the integral and fractional bits 
for _Accum types take up the width of the whole underlying integer to prevent 
having to mask out the padding bits when performing comparisons.


Repository:
  rC Clang

https://reviews.llvm.org/D47030

Files:
  cmake/modules/InitFixedPointBits.cmake

Index: cmake/modules/InitFixedPointBits.cmake
===
--- cmake/modules/InitFixedPointBits.cmake
+++ cmake/modules/InitFixedPointBits.cmake
@@ -60,26 +60,170 @@
   set(ULACCUM_IBIT 32)
 endif()
 
-# Checks for each bit size
+# Checks for each bit size defined in clause 6.2.6.3
+
+# Cannot go below the minimum number of fractional and integral bits for the
+# various types specified in clause 7.18a.3.
+function(assert_min_bits macro min_bits)
+  set("macro_name" ${macro})
+  set("macro_val" ${${macro}})
+  if(${macro_val} LESS ${min_bits})
+message(FATAL_ERROR "The minimum value allowed for ${macro_name} is ${min_bits}. "
+	"${macro_val} was provided.")
+  endif()
+endfunction()
+
+assert_min_bits(SFRACT_FBIT 7)
+assert_min_bits(FRACT_FBIT 15)
+assert_min_bits(LFRACT_FBIT 23)
+assert_min_bits(USFRACT_FBIT 7)
+assert_min_bits(UFRACT_FBIT 15)
+assert_min_bits(ULFRACT_FBIT 23)
+
+assert_min_bits(SACCUM_FBIT 7)
+assert_min_bits(ACCUM_FBIT 15)
+assert_min_bits(LACCUM_FBIT 23)
+assert_min_bits(USACCUM_FBIT 7)
+assert_min_bits(UACCUM_FBIT 15)
+assert_min_bits(ULACCUM_FBIT 23)
+
+assert_min_bits(SACCUM_IBIT 4)
+assert_min_bits(ACCUM_IBIT 4)
+assert_min_bits(LACCUM_IBIT 4)
+assert_min_bits(USACCUM_IBIT 4)
+assert_min_bits(UACCUM_IBIT 4)
+assert_min_bits(ULACCUM_IBIT 4)
+
 # Each unsigned fract type has either the same number of fractional bits as,
 # or one more fractional bit than, its corresponding signed fract type.
-# TODO: Implement remaining checks in clause 6.2.6.3.
-function(check_diff_at_most_1 sfract_fbits ufract_fbits)
-  if(sfract_fbits EQUAL ufract_fbits)
-return()
-  endif()
+function(assert_fract_diff sfract_fbits ufract_fbits)
   math(EXPR diff "${ufract_fbits} - ${sfract_fbits}")
-  if(diff EQUAL 1)
-return()
+  if(NOT((${diff} EQUAL 0) OR (${diff} EQUAL 1)))
+message(FATAL_ERROR "Each unsigned fract type must have either the same number of "
+  	"fractional bits as, or one more fractional bit than, its corresponding "
+  	"signed fract type.")
+  endif()
+endfunction()
+
+assert_fract_diff(${SFRACT_FBIT} ${USFRACT_FBIT})
+assert_fract_diff(${FRACT_FBIT} ${UFRACT_FBIT})
+assert_fract_diff(${LFRACT_FBIT} ${ULFRACT_FBIT})
+
+# When arranged in order of increasing rank (see 6.3.1.3a), the number of
+# fractional bits is nondecreasing for each of the following sets of
+# fixed-point types:
+# - signed fract types
+# - unsigned fract types
+# - signed accum types
+# - unsigned accum types.
+function(assert_non_decreasing short_type_bits middle_type_bits long_type_bits
+	 type_family bit_type)
+  if((${short_type_bits} GREATER ${middle_type_bits}) OR
+ (${middle_type_bits} GREATER ${long_type_bits}))
+message(FATAL_ERROR "The number of ${bit_type} bits in ${type_family} types must be "
+  	"non decreasing in order of increasing rank.")
+  endif()
+endfunction()
+
+assert_non_decreasing(${SFRACT_FBIT} ${FRACT_FBIT} ${LFRACT_FBIT} "signed _Fract" "fractional")
+assert_non_decreasing(${USFRACT_FBIT} ${UFRACT_FBIT} ${ULFRACT_FBIT} "unsigned _Fract" "fractional")
+assert_non_decreasing(${SACCUM_FBIT} ${ACCUM_FBIT} ${LACCUM_FBIT} "signed _Accum" "fractional")
+assert_non_decreasing(${USACCUM_FBIT} ${UACCUM_FBIT} ${ULACCUM_FBIT} "unsigned _Accum" "fractional")
+
+# When arranged in order of increasing rank (see 6.3.1.3a), the number of
+# integral bits is nondecreasing for each of the following sets of
+# fixed-point types:
+# - signed accum types
+# - unsigned accum types.
+assert_non_decreasing(${SACCUM_IBIT} ${ACCUM_IBIT} ${LACCUM_IBIT} "signed _Accum" "integral")
+assert_non_decreasing(${USACCUM_IBIT} ${UACCUM_IBIT} ${ULACCUM_IBIT} "unsigned _Accum" "integral")
+
+# Each signed accum type has at least as many integral bits as its
+# corresponding unsigned accum type.
+function(assert_integral_diff saccum_ibits uaccum_ibits)
+  if(${saccum_ibits} LESS ${uaccum_ibits})
+message(FATAL_ERROR "Each signed accum type must have at least as many integral bits as its "
+	"corresponding unsigned accum type.")
+  endif()
+endfunction()
+
+assert_integral_diff(${SACCUM_IBIT} ${USACCUM_IBIT})
+assert_integral_diff(${ACCUM_IBIT} ${UACCUM_IBIT})

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-17 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147386.
leonardchan added a comment.

Ran git-clang-tidy on all affected files


Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -542,6 +548,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/accum_errors.cpp
===
--- /dev/null
+++ test/Frontend/accum_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned _Accum u_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+
+short _Accum short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+_Accum accum; // expected-error{{Fixed point types are only allowed in C}}
+long _Accum long_accum;  // expected-error{{Fixed point types are only allowed in C}}
Index: test/Frontend/accum_errors.c
===
--- /dev/null
+++ test/Frontend/accum_errors.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
Index: test/Frontend/accum.c
===
--- /dev/null
+++ test/Frontend/accum.c
@@ -0,0 +1,26 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+/*  Various contexts where type _Accum can appear. */
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+
+// CHECK:  |-VarDecl {{.*}} s_short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum'
+// CHECK-NEXT: `-VarDecl {{.*}} long_accum 'long _Accum'
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -6816,6 +6816,24 @@
 case PREDEF_TYPE_LONGDOUBLE_ID:
   T = Context.LongDoubleTy;
   break;
+case PREDEF_TYPE_SHORT_ACCUM_ID:
+  T = Context.ShortAccumTy;
+  break;
+case PREDEF_TYPE_ACCUM_ID:
+  T = Context.AccumTy;
+  break;
+case PREDEF_TYPE_LONG_ACCUM_ID:
+  T = Co

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-17 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147400.
leonardchan added a comment.

Added break. We still assign `Result` since it cannot be null at the end of the 
switch stmt, though the value doesn't matter.

Added character `~` to indicate fixed point type followed by string detailing 
the type. I have not added a test to it because logically, I do not think we 
will ever reach that point. This logic is implemented in the `VisitType` 
method, which mostly gets called by visitors to c++ nodes like 
`VisitTemplateParameterList`, but we have disabled the use of fixed point types 
in c++. `VisitType` does get called in `VisitFunctionDecl` but the function 
exits early since we are not reading c++ (line lib/Index/USRGeneration.cpp:238).


Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -542,6 +548,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/accum_errors.cpp
===
--- /dev/null
+++ test/Frontend/accum_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned _Accum u_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+
+short _Accum short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+_Accum accum; // expected-error{{Fixed point types are only allowed in C}}
+long _Accum long_accum;  // expected-error{{Fixed point types are only allowed in C}}
Index: test/Frontend/accum_errors.c
===
--- /dev/null
+++ test/Frontend/accum_errors.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
Index: test/Frontend/accum.c
===
--- /dev/null
+++ test/Frontend/accum.c
@@ -0,0 +1,26 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+/*  Various contexts where type _Accum can appear. */
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+
+// CHECK:  |-VarDecl {{.*}} s_short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} short_a

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-17 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan marked 2 inline comments as done.
leonardchan added inline comments.



Comment at: lib/Index/USRGeneration.cpp:691
+case BuiltinType::ULongAccum:
+  llvm_unreachable("No USR name mangling for fixed point types.");
 case BuiltinType::Float16:

phosek wrote:
> We need some solution for fixed point types.
Added character ~ to indicate fixed point type followed by string detailing the 
type. I have not added a test to it because logically, I do not think we will 
ever reach that point. This logic is implemented in the VisitType method, which 
mostly gets called by visitors to c++ nodes like VisitTemplateParameterList, 
but we have disabled the use of fixed point types in c++. VisitType does get 
called in VisitFunctionDecl but the function exits early since we are not 
reading c++ (line lib/Index/USRGeneration.cpp:238).


Repository:
  rC Clang

https://reviews.llvm.org/D46084



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-17 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147406.
leonardchan marked an inline comment as done.
leonardchan added a comment.

Undid git-clang-formatting on ASTBitcodes.h


Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -542,6 +548,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/accum_errors.cpp
===
--- /dev/null
+++ test/Frontend/accum_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned _Accum u_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+
+short _Accum short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+_Accum accum; // expected-error{{Fixed point types are only allowed in C}}
+long _Accum long_accum;  // expected-error{{Fixed point types are only allowed in C}}
Index: test/Frontend/accum_errors.c
===
--- /dev/null
+++ test/Frontend/accum_errors.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
Index: test/Frontend/accum.c
===
--- /dev/null
+++ test/Frontend/accum.c
@@ -0,0 +1,26 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+/*  Various contexts where type _Accum can appear. */
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+
+// CHECK:  |-VarDecl {{.*}} s_short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum'
+// CHECK-NEXT: `-VarDecl {{.*}} long_accum 'long _Accum'
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -6816,6 +6816,24 @@
 case PREDEF_TYPE_LONGDOUBLE_ID:
   T = Context.LongDoubleTy;
   break;
+case PREDEF_TYPE_SHORT_ACCUM_ID:
+  T = Context.ShortAccumTy;
+  break;
+case PREDEF_TYPE_ACCUM_ID:
+  T = Context.AccumTy;
+  break;
+

[PATCH] D46911: [Fixed Point Arithmetic] Addition of the remaining fixed point types and their saturated equivalents

2018-05-18 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147541.
leonardchan added a comment.

Updated formatting


Repository:
  rC Clang

https://reviews.llvm.org/D46911

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_errors.cpp

Index: test/Frontend/fixed_point_errors.cpp
===
--- /dev/null
+++ test/Frontend/fixed_point_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;// expected-error{{Fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;// expected-error{{Fixed point types are only allowed in C}}
+unsigned _Accum u_accum;// expected-error{{Fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+
+short _Accum short_accum;   // expected-error{{Fixed point types are only allowed in C}}
+_Accum accum;   // expected-error{{Fixed point types are only allowed in C}}
+long _Accum long_accum; // expected-error{{Fixed point types are only allowed in C}}
Index: test/Frontend/fixed_point_errors.c
===
--- /dev/null
+++ test/Frontend/fixed_point_errors.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+long long _Fract longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+unsigned long long _Fract u_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+
+_Sat int i;  // expected-error{{'int' cannot be saturated. Only _Fract and _Accum can.}}
+_Sat _Sat _Fract fract;  // expected-warning{{duplicate '_Sat' declaration specifier}}
+
+_Sat long long _Accum sat_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+_Sat unsigned long long _Accum sat_u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+_Sat long long _Fract sat_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+_Sat unsigned long long _Fract sat_u_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
Index: test/Frontend/fixed_point.c
===
--- /dev/null
+++ test/Frontend/fixed_point.c
@@ -0,0 +1,82 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+signed short _Fract s_short_fract;
+signed _Fract s_fract;
+signed long _Fract s_long_fract;
+unsigned short _Fract u_short_fract;
+unsigned _Fract u_fract;
+unsigned long _Fract u_long_fract;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+short _Fract short_fract;
+_Fract fract;
+long _Fract long_fract;
+
+// Saturated fixed point types
+_Sat signed short _Accum sat_s_short_accum;
+_Sat signed _Accum sat_s_accum;
+_Sat signed long _Accum sat_s_long_accum;
+_Sat unsigned short _Accum sat_u_short_accum;
+_Sat unsigned _Accum sat_u_accum;
+_Sat unsigned long _Accum sat_u_long_accum;
+_Sat signed short _Fract sat_s_short_fract;
+_Sat signed _Fract sat_s_fract;
+_Sat signed long _Fract sat_s_long_fract;
+_Sat unsigned short _Fract sat_u_short_fract;
+_Sat unsigned _Fract sat_u_fract;
+_Sat unsigned long _Fract sat_u_long_fract;
+
+// Aliased saturated fixed point types
+_Sat short _Accum sat_short_accum;
+_Sat _Accum sat_accum;
+_Sat l

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-18 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147549.

Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -542,6 +548,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/accum_errors.cpp
===
--- /dev/null
+++ test/Frontend/accum_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned _Accum u_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+
+short _Accum short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+_Accum accum; // expected-error{{Fixed point types are only allowed in C}}
+long _Accum long_accum;  // expected-error{{Fixed point types are only allowed in C}}
Index: test/Frontend/accum_errors.c
===
--- /dev/null
+++ test/Frontend/accum_errors.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
Index: test/Frontend/accum.c
===
--- /dev/null
+++ test/Frontend/accum.c
@@ -0,0 +1,26 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+/*  Various contexts where type _Accum can appear. */
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+
+// CHECK:  |-VarDecl {{.*}} s_short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum'
+// CHECK-NEXT: `-VarDecl {{.*}} long_accum 'long _Accum'
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -6816,6 +6816,24 @@
 case PREDEF_TYPE_LONGDOUBLE_ID:
   T = Context.LongDoubleTy;
   break;
+case PREDEF_TYPE_SHORT_ACCUM_ID:
+  T = Context.ShortAccumTy;
+  break;
+case PREDEF_TYPE_ACCUM_ID:
+  T = Context.AccumTy;
+  break;
+case PREDEF_TYPE_LONG_ACCUM_ID:
+  T = Context.LongAccumTy;
+  break;
+case PREDEF_TYPE_USHORT_ACCUM_ID:

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-18 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147560.

Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -542,6 +548,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/accum_errors.cpp
===
--- /dev/null
+++ test/Frontend/accum_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned _Accum u_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+
+short _Accum short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+_Accum accum; // expected-error{{Fixed point types are only allowed in C}}
+long _Accum long_accum;  // expected-error{{Fixed point types are only allowed in C}}
Index: test/Frontend/accum_errors.c
===
--- /dev/null
+++ test/Frontend/accum_errors.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
Index: test/Frontend/accum.c
===
--- /dev/null
+++ test/Frontend/accum.c
@@ -0,0 +1,26 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+/*  Various contexts where type _Accum can appear. */
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+
+// CHECK:  |-VarDecl {{.*}} s_short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum'
+// CHECK-NEXT: `-VarDecl {{.*}} long_accum 'long _Accum'
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -6816,6 +6816,24 @@
 case PREDEF_TYPE_LONGDOUBLE_ID:
   T = Context.LongDoubleTy;
   break;
+case PREDEF_TYPE_SHORT_ACCUM_ID:
+  T = Context.ShortAccumTy;
+  break;
+case PREDEF_TYPE_ACCUM_ID:
+  T = Context.AccumTy;
+  break;
+case PREDEF_TYPE_LONG_ACCUM_ID:
+  T = Context.LongAccumTy;
+  break;
+case PREDEF_TYPE_USHORT_ACCUM_ID:

[PATCH] D46911: [Fixed Point Arithmetic] Addition of the remaining fixed point types and their saturated equivalents

2018-05-18 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147566.

Repository:
  rC Clang

https://reviews.llvm.org/D46911

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_errors.cpp

Index: test/Frontend/fixed_point_errors.cpp
===
--- /dev/null
+++ test/Frontend/fixed_point_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;// expected-error{{Fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;// expected-error{{Fixed point types are only allowed in C}}
+unsigned _Accum u_accum;// expected-error{{Fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+
+short _Accum short_accum;   // expected-error{{Fixed point types are only allowed in C}}
+_Accum accum;   // expected-error{{Fixed point types are only allowed in C}}
+long _Accum long_accum; // expected-error{{Fixed point types are only allowed in C}}
Index: test/Frontend/fixed_point_errors.c
===
--- /dev/null
+++ test/Frontend/fixed_point_errors.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+long long _Fract longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+unsigned long long _Fract u_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+
+_Sat int i;  // expected-error{{'int' cannot be saturated. Only _Fract and _Accum can.}}
+_Sat _Sat _Fract fract;  // expected-warning{{duplicate '_Sat' declaration specifier}}
+
+_Sat long long _Accum sat_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+_Sat unsigned long long _Accum sat_u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+_Sat long long _Fract sat_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+_Sat unsigned long long _Fract sat_u_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
Index: test/Frontend/fixed_point.c
===
--- /dev/null
+++ test/Frontend/fixed_point.c
@@ -0,0 +1,82 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+signed short _Fract s_short_fract;
+signed _Fract s_fract;
+signed long _Fract s_long_fract;
+unsigned short _Fract u_short_fract;
+unsigned _Fract u_fract;
+unsigned long _Fract u_long_fract;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+short _Fract short_fract;
+_Fract fract;
+long _Fract long_fract;
+
+// Saturated fixed point types
+_Sat signed short _Accum sat_s_short_accum;
+_Sat signed _Accum sat_s_accum;
+_Sat signed long _Accum sat_s_long_accum;
+_Sat unsigned short _Accum sat_u_short_accum;
+_Sat unsigned _Accum sat_u_accum;
+_Sat unsigned long _Accum sat_u_long_accum;
+_Sat signed short _Fract sat_s_short_fract;
+_Sat signed _Fract sat_s_fract;
+_Sat signed long _Fract sat_s_long_fract;
+_Sat unsigned short _Fract sat_u_short_fract;
+_Sat unsigned _Fract sat_u_fract;
+_Sat unsigned long _Fract sat_u_long_fract;
+
+// Aliased saturated fixed point types
+_Sat short _Accum sat_short_accum;
+_Sat _Accum sat_accum;
+_Sat long _Accum sat_long_accum;
+_Sat short _Fract sat_

[PATCH] D46911: [Fixed Point Arithmetic] Addition of the remaining fixed point types and their saturated equivalents

2018-05-18 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147568.

Repository:
  rC Clang

https://reviews.llvm.org/D46911

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_errors.cpp

Index: test/Frontend/fixed_point_errors.cpp
===
--- /dev/null
+++ test/Frontend/fixed_point_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;// expected-error{{Fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;// expected-error{{Fixed point types are only allowed in C}}
+unsigned _Accum u_accum;// expected-error{{Fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+
+short _Accum short_accum;   // expected-error{{Fixed point types are only allowed in C}}
+_Accum accum;   // expected-error{{Fixed point types are only allowed in C}}
+long _Accum long_accum; // expected-error{{Fixed point types are only allowed in C}}
Index: test/Frontend/fixed_point_errors.c
===
--- /dev/null
+++ test/Frontend/fixed_point_errors.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+long long _Fract longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+unsigned long long _Fract u_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+
+_Sat int i;  // expected-error{{'int' cannot be saturated. Only _Fract and _Accum can.}}
+_Sat _Sat _Fract fract;  // expected-warning{{duplicate '_Sat' declaration specifier}}
+
+_Sat long long _Accum sat_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+_Sat unsigned long long _Accum sat_u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+_Sat long long _Fract sat_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+_Sat unsigned long long _Fract sat_u_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
Index: test/Frontend/fixed_point.c
===
--- /dev/null
+++ test/Frontend/fixed_point.c
@@ -0,0 +1,82 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+signed short _Fract s_short_fract;
+signed _Fract s_fract;
+signed long _Fract s_long_fract;
+unsigned short _Fract u_short_fract;
+unsigned _Fract u_fract;
+unsigned long _Fract u_long_fract;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+short _Fract short_fract;
+_Fract fract;
+long _Fract long_fract;
+
+// Saturated fixed point types
+_Sat signed short _Accum sat_s_short_accum;
+_Sat signed _Accum sat_s_accum;
+_Sat signed long _Accum sat_s_long_accum;
+_Sat unsigned short _Accum sat_u_short_accum;
+_Sat unsigned _Accum sat_u_accum;
+_Sat unsigned long _Accum sat_u_long_accum;
+_Sat signed short _Fract sat_s_short_fract;
+_Sat signed _Fract sat_s_fract;
+_Sat signed long _Fract sat_s_long_fract;
+_Sat unsigned short _Fract sat_u_short_fract;
+_Sat unsigned _Fract sat_u_fract;
+_Sat unsigned long _Fract sat_u_long_fract;
+
+// Aliased saturated fixed point types
+_Sat short _Accum sat_short_accum;
+_Sat _Accum sat_accum;
+_Sat long _Accum sat_long_accum;
+_Sat short _Fract sat_

[PATCH] D46915: [Fixed Point Arithmetic] Set Fixed Point Precision Bits and Create Fixed Point Literals

2018-05-18 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147595.
leonardchan added a comment.

formatting


Repository:
  rC Clang

https://reviews.llvm.org/D46915

Files:
  CMakeLists.txt
  cmake/modules/InitFixedPointBits.cmake
  include/clang/AST/Expr.h
  include/clang/AST/OperationKinds.def
  include/clang/AST/RecursiveASTVisitor.h
  include/clang/AST/Type.h
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/FixedPoint.h.in
  include/clang/Basic/StmtNodes.td
  include/clang/Lex/LiteralSupport.h
  lib/AST/ASTContext.cpp
  lib/AST/ASTDumper.cpp
  lib/AST/Expr.cpp
  lib/AST/ExprClassification.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/StmtPrinter.cpp
  lib/AST/StmtProfile.cpp
  lib/AST/Type.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Lex/LiteralSupport.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExceptionSpec.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_declarations.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_validation.c
  tools/libclang/CXCursor.cpp

Index: tools/libclang/CXCursor.cpp
===
--- tools/libclang/CXCursor.cpp
+++ tools/libclang/CXCursor.cpp
@@ -305,6 +305,10 @@
 K = CXCursor_IntegerLiteral;
 break;
 
+  case Stmt::FixedPointLiteralClass:
+llvm_unreachable("No cursor for FixedPointLiteralClass");
+break;
+
   case Stmt::FloatingLiteralClass:
 K = CXCursor_FloatingLiteral;
 break;
Index: test/Frontend/fixed_point_validation.c
===
--- /dev/null
+++ test/Frontend/fixed_point_validation.c
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -S -emit-llvm -o - %s | lli
+
+// Run simple validation tests
+
+#define assert(b) if (!(b)) { return 1; }
+
+int main(){
+  short _Accum s_accum;
+  short _Accum s_accum2 = 2.0hk;
+  short _Fract s_fract = 0.999hr;
+  short _Fract s_fract2 = -0.999hr;
+
+  assert(s_accum == 0);
+
+  s_accum = s_accum2;
+
+  assert(s_accum == s_accum2);
+  assert(s_accum == 2);
+}
Index: test/Frontend/fixed_point_errors.c
===
--- test/Frontend/fixed_point_errors.c
+++ test/Frontend/fixed_point_errors.c
@@ -1,14 +1,23 @@
 // RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
 
-long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
-unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
-long long _Fract longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
-unsigned long long _Fract u_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;   // expected-error{{'long long _Accum' is invalid}}
+long long _Fract longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+unsigned long long _Fract u_longlong_fract;   // expected-error{{'long long _Fract' is invalid}}
 
 _Sat int i;  // expected-error{{'int' cannot be saturated. Only _Fract and _Accum can.}}
 _Sat _Sat _Fract fract;  // expected-warning{{duplicate '_Sat' declaration specifier}}
 
-_Sat long long _Accum sat_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+_Sat long long _Accum sat_longlong_accum; // expected-error{{'long long _Accum' is invalid}}
 _Sat unsigned long long _Accum sat_u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
-_Sat long long _Fract sat_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+_Sat long long _Fract sat_longlong_fract; // expected-error{{'long long _Fract' is invalid}}
 _Sat unsigned long long _Fract sat_u_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+
+short _Fract fract2 = 1.2hr;  // expected-error{{a _Fract type cannot have an integral part}}
+
+signed short _Accum s_short_accum = 129.0hk;  // expected-error{{the integral part of this literal is too large for this signed _Accum type}}
+unsigned short _Accum u_short_accum = 256.0uhk;   // expected-error{{the integral part of this literal is too large for this unsigned _Accum type}}
+signed _Accum s_accum = 32770.0k; // expected-error{{the integral part of this literal is too large for this signed _Accum type}}
+unsigned _Accum u_accum = 65536.0uk;  // expected-error{{the integral part of this literal is too large for this unsigned _Accum type}}
+short _Accum short_accum = 129.0hk;   // expected-error{{the integr

[PATCH] D46917: [Fixed Point Arithmetic] Comparison and Unary Operations for Fixed Point Types

2018-05-18 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147631.
leonardchan added a comment.

formatting


Repository:
  rC Clang

https://reviews.llvm.org/D46917

Files:
  lib/CodeGen/CGExprScalar.cpp
  lib/Sema/SemaExpr.cpp
  test/Frontend/fixed_point_declarations.c
  test/Frontend/fixed_point_validation.c

Index: test/Frontend/fixed_point_validation.c
===
--- test/Frontend/fixed_point_validation.c
+++ test/Frontend/fixed_point_validation.c
@@ -1,19 +1,170 @@
+// RUN: %clang -S -emit-llvm %s -o - | FileCheck %s
 // RUN: %clang_cc1 -S -emit-llvm -o - %s | lli
 
+// The first test checks the emitted llvm IR.
+// The second test checks the output.
+// Both these test require that the default bit widths for the fixed point types
+// are used since we check for bit shifted literals that were converted from
+// ints and floats.
+
+// Primary fixed point types
+signed short _Accum s_short_accum;// CHECK-DAG: @s_short_accum =  common dso_local global i16 0, align 2
+signed _Accum s_accum;// CHECK-DAG: @s_accum =common dso_local global i32 0, align 4
+signed long _Accum s_long_accum;  // CHECK-DAG: @s_long_accum =   common dso_local global i64 0, align 8
+unsigned short _Accum u_short_accum;  // CHECK-DAG: @u_short_accum =  common dso_local global i16 0, align 2
+unsigned _Accum u_accum;  // CHECK-DAG: @u_accum =common dso_local global i32 0, align 4
+unsigned long _Accum u_long_accum;// CHECK-DAG: @u_long_accum =   common dso_local global i64 0, align 8
+signed short _Fract s_short_fract;// CHECK-DAG: @s_short_fract =  common dso_local global i16 0, align 2
+signed _Fract s_fract;// CHECK-DAG: @s_fract =common dso_local global i32 0, align 4
+signed long _Fract s_long_fract;  // CHECK-DAG: @s_long_fract =   common dso_local global i64 0, align 8
+unsigned short _Fract u_short_fract;  // CHECK-DAG: @u_short_fract =  common dso_local global i16 0, align 2
+unsigned _Fract u_fract;  // CHECK-DAG: @u_fract =common dso_local global i32 0, align 4
+unsigned long _Fract u_long_fract;// CHECK-DAG: @u_long_fract =   common dso_local global i64 0, align 8
+
+// There are 7 bits allocated to the fractional part and 8
+// bits allocated to the integral part of a short _Accum by default.
+
+signed short _Accum s_short_accum2 = 2.5hk;  // CHECK-DAG: @s_short_accum2 = dso_local global i16 320, align 2
+short _Fract short_fract = 0.333hr;  // CHECK-DAG: @short_fract = dso_local global i16 42, align 2
+
 // Run simple validation tests
 
 #define assert(b) if (!(b)) { return 1; }
 
 int main(){
-  short _Accum s_accum;
+  short _Accum s_accum = 0.0hk;
   short _Accum s_accum2 = 2.0hk;
   short _Fract s_fract = 0.999hr;
   short _Fract s_fract2 = -0.999hr;
+  const _Fract fract_zero = 0.0r;
+  // CHECK:  %s_accum = alloca i16, align 2
+  // CHECK:  %s_accum2 = alloca i16, align 2
+  // CHECK:  %s_fract = alloca i16, align 2
+  // CHECK:  %s_fract2 = alloca i16, align 2
+  // CHECK:  %fract_zero = alloca i32, align 4
+  // CHECK:  store i16 0, i16* %s_accum, align 2
+  // CHECK:  store i16 256, i16* %s_accum2, align 2
+  // CHECK:  store i16 127, i16* %s_fract, align 2
+  // CHECK:  store i16 -127, i16* %s_fract2, align 2
+  // CHECK:  store i32 0, i32* %fract_zero, align 4
+
+  / Simple Comparisons ***/
 
   assert(s_accum == 0);
+  // CHECK:  {{.*}} = load i16, i16* %s_accum, align 2
+  // CHECK-NEXT: {{.*}} = icmp eq i16 {{.*}}, 0
 
   s_accum = s_accum2;
+  // CHECK:  {{.*}} = load i16, i16* %s_accum2, align 2
+  // CHECK-NEXT: store i16 %1, i16* %s_accum, align 2
 
   assert(s_accum == s_accum2);
+  // CHECK:  {{.*}} = load i16, i16* %s_accum, align 2
+  // CHECK-NEXT: {{.*}} = load i16, i16* %s_accum2, align 2
+  // CHECK-NEXT: {{.*}} = icmp eq i16 {{.*}}, {{.*}}
+
+  assert(s_accum2 == s_accum);
+  // CHECK:  {{.*}} = load i16, i16* %s_accum2, align 2
+  // CHECK-NEXT: {{.*}} = load i16, i16* %s_accum, align 2
+  // CHECK-NEXT: {{.*}} = icmp eq i16 {{.*}}, {{.*}}
+
   assert(s_accum == 2);
+  // CHECK:  {{.*}} = icmp eq i16 {{.*}}, 256
+
+  assert(2 == s_accum);
+  // CHECK:  {{.*}} = icmp eq i16 256, {{.*}}
+
+  int x = 2;
+  assert(s_accum == x);
+  // CHECK:  {{.*}} = load i32, i32* %x, align 4
+  // CHECK-NEXT: {{.*}} = trunc i32 {{.*}} to i16
+  // CHECK-NEXT: {{.*}} = shl i16 {{.*}}, 7
+  // CHECK-NEXT: {{.*}} = icmp eq i16 {{.*}}, {{.*}}
+
+  assert(x == s_accum);
+
+  assert(s_accum != -2);
+  // CHECK:  {{.*}} = icmp ne i16 {{.*}}, -256
+
+  assert(-2 != s_accum);
+  // CHECK:  {{.*}} = icmp ne i16 -256, {{.*}}
+
+  assert(s_accum != -x);
+  assert(-x != s_accum);
+
+  assert(s_fract != 1);
+  // CHECK:  {{.*}} = load i16, i16* %s_fract, align 2
+  // CHECK_NEXT: {{.*}} = icmp ne i16 {{.*}}, 128
+
+  assert(s_fract2 != -1);
+  // CHECK:  {

[PATCH] D46925: [Fixed Point Arithmetic] Remaining Binary Operations on Primary Fixed Point Types

2018-05-21 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147880.
leonardchan added a comment.

formatting


Repository:
  rC Clang

https://reviews.llvm.org/D46925

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/OperationKinds.def
  include/clang/AST/Type.h
  lib/AST/ASTContext.cpp
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/Type.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Sema/SemaExpr.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point_validation.c

Index: test/Frontend/fixed_point_validation.c
===
--- test/Frontend/fixed_point_validation.c
+++ test/Frontend/fixed_point_validation.c
@@ -74,6 +74,9 @@
   assert(2 == s_accum);
   // CHECK:  {{.*}} = icmp eq i16 256, {{.*}}
 
+  assert(2 == 2.0hk);
+  assert(2 != 2.01hk);
+
   int x = 2;
   assert(s_accum == x);
   // CHECK:  {{.*}} = load i32, i32* %x, align 4
@@ -128,6 +131,46 @@
   // numbers.
   assert(2 == 2.001hk);  // This is valid if SACCUM_FBITS == 7
 
+  // Comparisons between fixed-point types
+  // Signed _Accum to signed _Accum types.
+  assert(2.5hk == 2.5k);
+  assert(2.5k == 2.5lk);
+  assert(-2.5hk == -2.5k);
+  assert(-2.5k == -2.5lk);
+
+  // Unsigned _Accum to unigned _Accum
+  assert(2.5uhk == 2.5uk);
+  assert(2.5uk == 2.5ulk);
+
+  // Signed _Fract to signed _Fract types.
+  assert(0.333hr != 0.333r);  // Loss of precision since different fractional widths
+  assert(0.333r != 0.333lr);
+  assert(-0.333hr != -0.333r);
+  assert(-0.333r != -0.333lr);
+
+  // Unsigned _Fract to unsigned _Fract types.
+  assert(0.333uhr != 0.333ur);
+  assert(0.333ur != 0.333ulr);
+
+  // Signed _Accum to signed _Fract
+  assert(0.333hk == 0.333hr);
+  assert(0.333k == 0.333r);
+  assert(0.333lk == 0.333lr);
+  assert(0.333hk == 0.333r);  // Although _Fract has higher precision, it gets casted up to
+  // short _Accum which (using default precisions)
+  // has fewer fractional bits.
+
+  // Signed _Accum to unsigned _Fract
+  assert(0.333hk == 0.333uhr);
+  assert(0.333k == 0.333ur);
+  assert(0.333lk == 0.333ulr);
+
+  // Signed _Accum to unsigned _Accum
+  assert(2.5hk == 2.5uhk);
+  assert(2.5k == 2.5uk);
+  assert(2.5lk == 2.5ulk);
+
+
   / Unary operations ***/
 
   s_accum = 0.0hk;
@@ -167,4 +210,58 @@
   assert(+s_fract == s_fract);
   assert(+s_fract2 == s_fract2);  // s_fract2 is negative
   assert(-s_fract == s_fract2);
+
+  / Binary operations ***/
+
+  // Addition
+  s_accum = 3.0hk;
+  short _Accum s_accum_sum = s_accum + s_accum2;
+  assert(s_accum_sum == 5);
+  assert(s_fract + s_fract2 == 0);
+
+  // Subtraction
+  short _Accum s_accum_diff = s_accum - s_accum2;
+  assert(s_accum_diff == 1);
+  assert(s_accum2 - s_accum == -1);
+
+  // Multiplication
+  short _Accum s_accum_mul = s_accum * s_accum2;
+  assert(s_accum_mul == 6);
+  assert(2.0hk * 3.0hk == 6);
+  assert(2.0hk * 3 == 6);
+  assert(2.5hk * 3 == 7.5k);
+  assert(-2.5hk * 3 == -7.5lk);
+  assert(3 * -2.5hk == -7.5hk);
+  assert(-2.5hk * 0 == 0);
+
+  // Division
+  const short _Accum s_accum3 = 2.5hk;
+  short _Accum s_accum_div = s_accum3 / s_accum2;
+  assert(s_accum_div == 1.25hk);
+  assert(5.0hk / s_accum3 == 2);
+  assert(-5.0hk / s_accum3 == -2);
+  assert(9.9k / 3.3k == 3);
+  assert(9.9hk / 3.3k != 3);  // We lose precision when converting between types of different
+  // fractional width.
+  assert(6.75hk / 2.25k == 3);  // Unless the fractional part can be evenly represented with
+// sums of powers of 2.
+  assert(0 / 2.0hk == 0);
+
+  // Left shift
+  short _Accum s_accum_shl = s_accum2 << 3;
+  assert(s_accum_shl == 16);
+  assert(1.0hk << 3 == 8);
+  assert(-1.0hk << 3 == -8);
+  assert(1.5k << 1 == 3);  // LShift is equivalent to multiplying by 2
+  assert(-1.25hk << 2 == -5);
+
+  // Right shift
+  const signed short _Accum s_accum4 = 16.0hk;
+  short _Accum s_accum_shr = s_accum4 >> 3;
+  assert(s_accum_shr == 2);
+  assert(s_accum_shr >> 1 == 1);
+  assert(s_accum_shr >> 2 == 0.5hr);  // RShift is equivalent to dividing by 2
+  assert(5.0hk >> 2 == 1.25hk);
+  assert(-5.0hk >> 2 == -1.25k);
+  assert(0.0hr >> 2 == 0);
 }
Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp
===
--- lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -321,6 +321,8 @@
 const LocationContext *LCtx = Pred->getLocationContext();
 
 switch (CastE->getCastKind()) {
+  case CK_FixedPointCast:
+llvm_unreachable("CK_FixedPointCast");  // TODO
   case CK_IntegralToFixedPoint:
 llvm_unreachable(
 "ExprEngine::VisitCast CK_IntegralToF

[PATCH] D46926: [Fixed Point Arithmetic] Conversion between Fixed Point and Floating Point Numbers

2018-05-21 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147881.
leonardchan added a comment.

formatting


Repository:
  rC Clang

https://reviews.llvm.org/D46926

Files:
  include/clang/AST/OperationKinds.def
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Sema/SemaCast.cpp
  lib/Sema/SemaExpr.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point_validation.c

Index: test/Frontend/fixed_point_validation.c
===
--- test/Frontend/fixed_point_validation.c
+++ test/Frontend/fixed_point_validation.c
@@ -30,6 +30,7 @@
 // Run simple validation tests
 
 #define assert(b) if (!(b)) { return 1; }
+#define abs(x) x < 0 ? -x : x
 
 int main(){
   short _Accum s_accum = 0.0hk;
@@ -264,4 +265,18 @@
   assert(5.0hk >> 2 == 1.25hk);
   assert(-5.0hk >> 2 == -1.25k);
   assert(0.0hr >> 2 == 0);
+
+  / Float conversions ***/
+
+  float f = (float)2.5k;
+  assert(f > 2.4999 && f < 2.5001);  // High precision since the fractional
+ // value can be evenly represented.
+  assert((float)2.333hk != 2.333f);
+
+  float base = 2.333f;
+  float saccum_diff = abs(base - 2.333hk);
+  float accum_diff = abs(base - 2.333k);
+  float laccum_diff = abs(base - 2.333lk);
+  assert(accum_diff < saccum_diff);
+  assert(laccum_diff < accum_diff);
 }
Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp
===
--- lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -326,6 +326,8 @@
   case CK_IntegralToFixedPoint:
 llvm_unreachable(
 "ExprEngine::VisitCast CK_IntegralToFixedPoint");  // TODO
+  case CK_FixedPointToFloating:
+llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating");
   case CK_LValueToRValue:
 llvm_unreachable("LValueToRValue casts handled earlier.");
   case CK_ToVoid:
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -1029,6 +1029,21 @@
   return result;
 }
 
+/// \brief Handle arithmetic conversion from fixed point to floating.  Helper
+/// function of UsualArithmeticConversions()
+static QualType handleFixedPointToFloatConversion(Sema &S,
+  ExprResult &FloatExpr,
+  ExprResult &FixedPointExpr,
+  QualType FloatTy,
+  QualType FixedPointTy) {
+  assert(FloatTy->isFloatingType());
+  assert(FixedPointTy->isFixedPointType());
+
+  FixedPointExpr = S.ImpCastExprToType(FixedPointExpr.get(), FloatTy,
+   CK_FixedPointToFloating);
+  return FloatTy;
+}
+
 /// \brief Handle arithmethic conversion with floating point types.  Helper
 /// function of UsualArithmeticConversions()
 static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
@@ -1057,11 +1072,20 @@
 if (LHSType->isHalfType() && !S.getLangOpts().NativeHalfType)
   LHSType = S.Context.FloatTy;
 
+if (RHSType->isFixedPointType()) {
+  return handleFixedPointToFloatConversion(S, LHS, RHS, LHSType, RHSType);
+}
+
 return handleIntToFloatConversion(S, LHS, RHS, LHSType, RHSType,
   /*convertFloat=*/!IsCompAssign,
   /*convertInt=*/ true);
   }
   assert(RHSFloat);
+
+  if (LHSType->isFixedPointType()) {
+return handleFixedPointToFloatConversion(S, RHS, LHS, RHSType, LHSType);
+  }
+
   return handleIntToFloatConversion(S, RHS, LHS, RHSType, LHSType,
 /*convertInt=*/ true,
 /*convertFloat=*/!IsCompAssign);
@@ -1218,6 +1242,7 @@
   CK_IntegralRealToComplex);
   return ComplexType;
 }
+
 /// \brief Handle arithmetic conversion from integer to fixed point.  Helper
 /// function of UsualArithmeticConversions()
 static QualType handleIntToFixedPointConversion(Sema &S,
@@ -6041,9 +6066,20 @@
 }
 llvm_unreachable("Should have returned before this");
 
-  case Type::STK_FixedPoint:
-llvm_unreachable(
-"Sema::PrepareScalarCast from STK_FixedPoint to anything");  // TODO
+  case Type::STK_FixedPoint: {
+switch (DestTy->getScalarTypeKind()) {
+  default:
+llvm_unreachable("Unable to convert from fixed point type");
+  case Type::STK_Integral:
+llvm_unreachable(
+"Unimplemented scalar cast from fixed point to int");  // TODO
+  case Type::STK_Floating:
+return CK_FixedPointToFloat

[PATCH] D46927: [Fixed Point Arithmetic] Augmented Assignment for Fixed Point Types

2018-05-21 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147882.
leonardchan added a comment.

formatting


Repository:
  rC Clang

https://reviews.llvm.org/D46927

Files:
  include/clang/AST/Type.h
  lib/AST/Type.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Sema/SemaExpr.cpp
  test/Frontend/fixed_point_validation.c

Index: test/Frontend/fixed_point_validation.c
===
--- test/Frontend/fixed_point_validation.c
+++ test/Frontend/fixed_point_validation.c
@@ -1,5 +1,5 @@
-// RUN: %clang -S -emit-llvm %s -o - | FileCheck %s
 // RUN: %clang_cc1 -S -emit-llvm -o - %s | lli
+// RUN: %clang -S -emit-llvm %s -o - | FileCheck %s
 
 // The first test checks the emitted llvm IR.
 // The second test checks the output.
@@ -279,4 +279,35 @@
   float laccum_diff = abs(base - 2.333lk);
   assert(accum_diff < saccum_diff);
   assert(laccum_diff < accum_diff);
+
+  / Auxillary assignments ***/
+
+  s_accum = 7.5hk;
+  s_accum2 = 2.0hk;
+  s_accum += s_accum2;
+  assert(s_accum == 9.5hk);
+  s_accum += 2.5k;
+  assert(s_accum == 12);
+
+  s_accum -= s_accum2;
+  assert(s_accum == 10);
+  s_accum -= 2.5lk;
+  assert(s_accum == 7.5k);
+
+  s_accum2 = 3.0k;
+  s_accum *= s_accum2;
+  assert(s_accum == 22.5k);
+  s_accum *= 0.5r;
+  assert(s_accum == 11.25hk);
+
+  s_accum /= s_accum2;
+  assert(s_accum == 3.75k);
+  s_accum /= 0.5hr;
+  assert(s_accum == 7.5k);
+
+  s_accum <<= 3;
+  assert(s_accum == 60);
+
+  s_accum >>= 3;
+  assert(s_accum == 7.5k);
 }
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -6076,8 +6076,7 @@
   case Type::STK_Floating:
 return CK_FixedPointToFloating;
   case Type::STK_FixedPoint:
-llvm_unreachable(
-"Unimplemented scalar cast from fixed point to fixed point");  // TODO
+return CK_FixedPointCast;
 }
   }
 
Index: lib/CodeGen/CGExprScalar.cpp
===
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -308,6 +308,17 @@
   Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
   SourceLocation Loc, bool TreatBooleanAsSigned);
 
+  /// Emit a conversion between fixed point types by moving the radix point.
+  /// This does not take into account resizing of the underlying llvm type
+  /// which should be handled either before or after calling this function.
+  ///
+  /// If the type is being scaled up, this method should be called after
+  /// performing an intcast. If the type is scaled down, this method should be
+  /// called before performing an intcast. This is necessary such that the
+  /// shift operations retain as much of the original data as possible before
+  /// truncation or after extension.
+  Value *EmitFixedPointRadixShift(Value *Src, QualType SrcTy, QualType DstTy);
+
   /// Emit a conversion from the specified complex type to the specified
   /// destination type, where the destination type is an LLVM scalar type.
   Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
@@ -961,6 +972,49 @@
 SanitizerHandler::FloatCastOverflow, StaticArgs, OrigSrc);
 }
 
+/// Emit a conversion between fixed point types by moving the radix point.
+/// This does not take into account resizing of the underlying llvm type
+/// which should be handled either before or after calling this function.
+///
+/// If the type is being scaled up, this method should be called after
+/// performing an intcast. If the type is scaled down, this method should be
+/// called before performing an intcast. This is necessary such that the
+/// shift operations retain as much of the original data as possible before
+/// truncation or after extension.
+Value *ScalarExprEmitter::EmitFixedPointRadixShift(Value *Src, QualType SrcTy,
+   QualType DstTy) {
+  assert(DstTy->isFixedPointType());
+  assert(SrcTy->isFixedPointType());
+
+  Value *Res = Src;
+
+  // Casting between fixed point types involves separating the integral and
+  // fractional bits, potentially shifting them, then joining back together.
+  unsigned dest_fbits = getFixedPointFBits(DstTy);
+  unsigned src_fbits = getFixedPointFBits(SrcTy);
+  unsigned dest_ibits = getFixedPointIBits(DstTy);
+  unsigned src_ibits = getFixedPointIBits(SrcTy);
+
+  // If the number of integral bits is decreasing, trim off any extra bits while
+  // retaining the sign.
+  if (dest_ibits < src_ibits) {
+Res = Builder.CreateShl(Res, src_ibits - dest_ibits);
+Res = Builder.CreateAShr(Res, src_ibits - dest_ibits);
+  }
+
+  // Move the radix. For irrational numbers, there will be loss of precision
+  // using this method when the number of fbits increases since we will be right
+  // padding zeros. Precision can still be retained if we temporarily convert to

[PATCH] D46960: [Fixed Point Arithmetic] Predefined Precision Macros

2018-05-21 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147883.
leonardchan added a comment.

formatting


Repository:
  rC Clang

https://reviews.llvm.org/D46960

Files:
  include/clang/Lex/Preprocessor.h
  lib/Lex/PPMacroExpansion.cpp
  test/Frontend/fixed_point_builtin_macros.c

Index: test/Frontend/fixed_point_builtin_macros.c
===
--- /dev/null
+++ test/Frontend/fixed_point_builtin_macros.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -S -emit-llvm -o - %s | lli
+
+#define assert(b) if (!(b)) { return 1; }
+
+int main() {
+  // Test using the recommended values for a typical desktop processor (Annex
+  // A.3). These are also the default values when building clang.
+  // Fractional bits of _Accum types
+  assert(__SACCUM_FBIT__  == 7);
+  assert(__ACCUM_FBIT__   == 15);
+  assert(__LACCUM_FBIT__  == 31);
+  assert(__USACCUM_FBIT__ == 8);
+  assert(__UACCUM_FBIT__  == 16);
+  assert(__ULACCUM_FBIT__ == 32);
+
+  // Fractional bits of _Fract types
+  assert(__SFRACT_FBIT__  == 7);
+  assert(__FRACT_FBIT__   == 15);
+  assert(__LFRACT_FBIT__  == 31);
+  assert(__USFRACT_FBIT__ == 8);
+  assert(__UFRACT_FBIT__  == 16);
+  assert(__ULFRACT_FBIT__ == 32);
+
+  // Integral bits of _Accum types
+  assert(__SACCUM_IBIT__  == 8);
+  assert(__ACCUM_IBIT__   == 16);
+  assert(__LACCUM_IBIT__  == 32);
+  assert(__USACCUM_IBIT__ == 8);
+  assert(__UACCUM_IBIT__  == 16);
+  assert(__ULACCUM_IBIT__ == 32);
+}
Index: lib/Lex/PPMacroExpansion.cpp
===
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -14,6 +14,7 @@
 
 #include "clang/Basic/Attributes.h"
 #include "clang/Basic/FileManager.h"
+#include "clang/Basic/FixedPoint.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/LangOptions.h"
@@ -355,6 +356,31 @@
   Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro(*this, "__INCLUDE_LEVEL__");
   Ident__TIMESTAMP__ = RegisterBuiltinMacro(*this, "__TIMESTAMP__");
 
+  // Fixed point macros (ISO/IEC JTC1 SC22 WG14 N1169)
+  // Fractional bits of _Accum types
+  Ident__SACCUM_FBIT__   = RegisterBuiltinMacro(*this, "__SACCUM_FBIT__");
+  Ident__ACCUM_FBIT__= RegisterBuiltinMacro(*this, "__ACCUM_FBIT__");
+  Ident__LACCUM_FBIT__   = RegisterBuiltinMacro(*this, "__LACCUM_FBIT__");
+  Ident__USACCUM_FBIT__  = RegisterBuiltinMacro(*this, "__USACCUM_FBIT__");
+  Ident__UACCUM_FBIT__   = RegisterBuiltinMacro(*this, "__UACCUM_FBIT__");
+  Ident__ULACCUM_FBIT__  = RegisterBuiltinMacro(*this, "__ULACCUM_FBIT__");
+
+  // Fractional bits of _Fract types
+  Ident__SFRACT_FBIT__   = RegisterBuiltinMacro(*this, "__SFRACT_FBIT__");
+  Ident__FRACT_FBIT__= RegisterBuiltinMacro(*this, "__FRACT_FBIT__");
+  Ident__LFRACT_FBIT__   = RegisterBuiltinMacro(*this, "__LFRACT_FBIT__");
+  Ident__USFRACT_FBIT__  = RegisterBuiltinMacro(*this, "__USFRACT_FBIT__");
+  Ident__UFRACT_FBIT__   = RegisterBuiltinMacro(*this, "__UFRACT_FBIT__");
+  Ident__ULFRACT_FBIT__  = RegisterBuiltinMacro(*this, "__ULFRACT_FBIT__");
+
+  // Integral bits of _Accum types
+  Ident__SACCUM_IBIT__   = RegisterBuiltinMacro(*this, "__SACCUM_IBIT__");
+  Ident__ACCUM_IBIT__= RegisterBuiltinMacro(*this, "__ACCUM_IBIT__");
+  Ident__LACCUM_IBIT__   = RegisterBuiltinMacro(*this, "__LACCUM_IBIT__");
+  Ident__USACCUM_IBIT__  = RegisterBuiltinMacro(*this, "__USACCUM_IBIT__");
+  Ident__UACCUM_IBIT__   = RegisterBuiltinMacro(*this, "__UACCUM_IBIT__");
+  Ident__ULACCUM_IBIT__  = RegisterBuiltinMacro(*this, "__ULACCUM_IBIT__");
+
   // Microsoft Extensions.
   if (LangOpts.MicrosoftExt) {
 Ident__identifier = RegisterBuiltinMacro(*this, "__identifier");
@@ -1696,6 +1722,68 @@
 // __LINE__ expands to a simple numeric value.
 OS << (PLoc.isValid()? PLoc.getLine() : 1);
 Tok.setKind(tok::numeric_constant);
+
+  // Fixed point macros
+  // Fractional bits of _Accum types
+  } else if (II == Ident__SACCUM_FBIT__) {
+OS << BUILTIN_SACCUM_FBIT;
+Tok.setKind(tok::numeric_constant);
+  } else if (II == Ident__ACCUM_FBIT__) {
+OS << BUILTIN_ACCUM_FBIT;
+Tok.setKind(tok::numeric_constant);
+  } else if (II == Ident__LACCUM_FBIT__) {
+OS << BUILTIN_LACCUM_FBIT;
+Tok.setKind(tok::numeric_constant);
+  } else if (II == Ident__USACCUM_FBIT__) {
+OS << BUILTIN_USACCUM_FBIT;
+Tok.setKind(tok::numeric_constant);
+  } else if (II == Ident__UACCUM_FBIT__) {
+OS << BUILTIN_UACCUM_FBIT;
+Tok.setKind(tok::numeric_constant);
+  } else if (II == Ident__ULACCUM_FBIT__) {
+OS << BUILTIN_ULACCUM_FBIT;
+Tok.setKind(tok::numeric_constant);
+
+  // Fractional bits of _Fract types
+  } else if (II == Ident__SFRACT_FBIT__) {
+OS << BUILTIN_SFRACT_FBIT;
+Tok.setKind(tok::numeric_constant);
+  } else if (II == Ident__FRACT_FBIT__) {
+OS << BUILTIN_FRACT_FBIT;
+Tok.setKind(tok::numeric_constant);
+  } else if (II == Ident__LFRACT_FBIT__) {
+OS << BUILTIN_LFRA

[PATCH] D46963: [Fixed Point Arithmetic] Test for All Builtin Operations

2018-05-21 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147888.
leonardchan added a comment.

formatting


Repository:
  rC Clang

https://reviews.llvm.org/D46963

Files:
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGExprScalar.cpp
  test/Frontend/fixed_point_all_builtin_operations.c

Index: test/Frontend/fixed_point_all_builtin_operations.c
===
--- /dev/null
+++ test/Frontend/fixed_point_all_builtin_operations.c
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -Werror %s
+
+// Check that we can use all supported binary and unary operations according to
+// clause 4.1.6 in N1169.
+
+#define ALL_OPERATIONS_FOR_TYPE(TYPE, ID) \
+  TYPE unary_add##ID(TYPE a) { return +a; }   \
+  TYPE unary_sub##ID(TYPE a) { return -a; }   \
+  int logical_not##ID(TYPE a) { return !a; }  \
+  TYPE add##ID(TYPE a, TYPE b) { return a + b; }  \
+  TYPE sub##ID(TYPE a, TYPE b) { return a - b; }  \
+  TYPE mul##ID(TYPE a, TYPE b) { return a * b; }  \
+  TYPE div##ID(TYPE a, TYPE b) { return a / b; }  \
+  TYPE shl##ID(TYPE a, int b) { return a << b; }  \
+  TYPE shr##ID(TYPE a, int b) { return a >> b; }  \
+  TYPE augmented_add##ID(TYPE a, TYPE b) {\
+a += b;   \
+return a; \
+  }   \
+  TYPE augmented_sub##ID(TYPE a, TYPE b) {\
+a -= b;   \
+return a; \
+  }   \
+  TYPE augmented_mul##ID(TYPE a, TYPE b) {\
+a *= b;   \
+return a; \
+  }   \
+  TYPE augmented_div##ID(TYPE a, TYPE b) {\
+a /= b;   \
+return a; \
+  }   \
+  TYPE augmented_shl##ID(TYPE a, int b) { \
+a <<= b;  \
+return a; \
+  }   \
+  TYPE augmented_shr##ID(TYPE a, int b) { \
+a >>= b;  \
+return a; \
+  }   \
+  int eq##ID(TYPE a, TYPE b) { return a == b; }   \
+  int ne##ID(TYPE a, TYPE b) { return a != b; }   \
+  int lt##ID(TYPE a, TYPE b) { return a < b; }\
+  int le##ID(TYPE a, TYPE b) { return a <= b; }   \
+  int ge##ID(TYPE a, TYPE b) { return a >= b; }   \
+  int gt##ID(TYPE a, TYPE b) { return a > b; }\
+  TYPE pre_inc##ID(TYPE a) { return ++a; }\
+  TYPE pre_dec##ID(TYPE a) { return --a; }\
+  TYPE post_inc##ID(TYPE a) { return a++; }   \
+  TYPE post_dec##ID(TYPE a) { return a--; }   \
+  TYPE deref_pre_inc##ID(TYPE *a) { return ++(*a); }  \
+  TYPE deref_pre_dec##ID(TYPE *a) { return --(*a); }  \
+  TYPE deref_post_inc##ID(TYPE *a) { return (*a)++; } \
+  TYPE deref_post_dec##ID(TYPE *a) { return (*a)--; }
+
+#define ALL_OPERATIONS(TYPE, ID)   \
+  ALL_OPERATIONS_FOR_TYPE(TYPE, ID)\
+  ALL_OPERATIONS_FOR_TYPE(signed TYPE, Signed##ID) \
+  ALL_OPERATIONS_FOR_TYPE(unsigned TYPE, Unsigned##ID) \
+  ALL_OPERATIONS_FOR_TYPE(_Sat TYPE, Sat##ID)  \
+  ALL_OPERATIONS_FOR_TYPE(_Sat signed TYPE, SatSigned##ID) \
+  ALL_OPERATIONS_FOR_TYPE(_Sat unsigned TYPE, SatUnsigned##ID)
+
+ALL_OPERATIONS(short _Fract, ShortFract);
+ALL_OPERATIONS(_Fract, Fract);
+ALL_OPERATIONS(long _Fract, LongFract);
+ALL_OPERATIONS(short _Accum, ShortAccum);
+ALL_OPERATIONS(_Accum, Accum);
+ALL_OPERATIONS(long _Accum, LongAccum);
Index: lib/CodeGen/CGExprScalar.cpp
===
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -2214,39 +2214,51 @@
 switch (BT->getKind()) {
   default:
 llvm_unreachable("Not a fixed point type!");
+  case BuiltinType::SatShortAccum:
   case BuiltinType::ShortAccum:
 fbits = BUILTIN_SACCUM_FBIT;
 break;
+  case BuiltinType::SatAccum:
   case BuiltinType::Accum:
 fbits = BUILTIN_ACCUM_FBIT;
 break;
+  case BuiltinType::SatLongAccum:
   case BuiltinType::LongAccum:
 fbits = BUILTIN_LACCUM_FBIT;
 break;
+  case BuiltinType::SatUShortAccum:
   case BuiltinType::UShortAccum:
 fbits = BUILTIN_USACCUM_FBIT;
 break;
+  case BuiltinType::SatUAccum:
   case BuiltinType::UAccum:
 fbits = BUILTIN_UACCUM_FBIT;
 break;
+  case BuiltinType::SatULongAccum:

[PATCH] D46979: [Fixed Point Arithmetic] Test for Conversion Between Valid Builtin Types

2018-05-21 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 147902.
leonardchan added a comment.

formatting


Repository:
  rC Clang

https://reviews.llvm.org/D46979

Files:
  include/clang/AST/OperationKinds.def
  lib/AST/Expr.cpp
  lib/AST/ExprConstant.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Sema/SemaExpr.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point_all_conversions.c

Index: test/Frontend/fixed_point_all_conversions.c
===
--- /dev/null
+++ test/Frontend/fixed_point_all_conversions.c
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -Werror %s
+
+// Test for conversions between fixed point types and all other valid types.
+
+// Conversion from one type to another type
+#define CONVERT(FROM_TYPE, FROM_ID, TO_TYPE, TO_ID) \
+  TO_TYPE FROM_ID##_to_##TO_ID(FROM_TYPE x) { return x; }
+
+// Conversion between 2 types
+#define CONVERT_COMBINATION(TYPE1, ID1, TYPE2, ID2) \
+  CONVERT(TYPE1, ID1, TYPE2, ID2)   \
+  CONVERT(TYPE2, ID2, TYPE1, ID1)
+
+// Conversion between one type and floating point types
+#define CONVERT_BETWEEN_FLOATS(TYPE, ID)  \
+  CONVERT_COMBINATION(TYPE, ID, float, Float) \
+  CONVERT_COMBINATION(TYPE, ID, double, Double)
+
+// Conversion between one type and an integral type with differant signage
+#define CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, INT_TYPE, INT_ID) \
+  CONVERT_COMBINATION(TYPE, ID, INT_TYPE, INT_ID)   \
+  CONVERT_COMBINATION(TYPE, ID, signed INT_TYPE, Signed##INT_ID)\
+  CONVERT_COMBINATION(TYPE, ID, unsigned INT_TYPE, Unsigned##INT_ID)
+
+// Conversion between one type and all integral types
+#define CONVERT_BETWEEN_INTEGRALS(TYPE, ID)   \
+  CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, char, Char)   \
+  CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, short, Short) \
+  CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, int, Int) \
+  CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, long, Long)   \
+  CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, long long, LongLong)
+
+// Conversion between one type and a fixed point type with different saturation
+#define CONVERT_BETWEEN_FIXED_POINT_WITH_SAT(TYPE, ID, FIXED_TYPE, FIXED_ID) \
+  CONVERT_COMBINATION(TYPE, ID, FIXED_TYPE, FIXED_ID)\
+  CONVERT_COMBINATION(TYPE, ID, _Sat FIXED_TYPE, Sat##FIXED_ID)
+
+// Conversion between one type and a fixed point type with different signage
+#define CONVERT_BETWEEN_FIXED_POINT_WITH_SIGN(TYPE, ID, FIXED_TYPE, FIXED_ID) \
+  CONVERT_BETWEEN_FIXED_POINT_WITH_SAT(TYPE, ID, FIXED_TYPE, FIXED_ID)\
+  CONVERT_BETWEEN_FIXED_POINT_WITH_SAT(TYPE, ID, signed FIXED_TYPE,   \
+   Signed##FIXED_ID)  \
+  CONVERT_BETWEEN_FIXED_POINT_WITH_SAT(TYPE, ID, unsigned FIXED_TYPE, \
+   Unsigned##FIXED_ID)
+
+// Convert between one type and all fixed point types.
+// Add "Type" to the end of the ID to avoid multiple definitions of a function
+// if the Type is a fixed point type.
+#define CONVERT_BETWEEN_FIXED_POINT(TYPE, ID)\
+  CONVERT_BETWEEN_FIXED_POINT_WITH_SIGN(TYPE, ID, _Fract, FractType) \
+  CONVERT_BETWEEN_FIXED_POINT_WITH_SIGN(TYPE, ID, _Accum, AccumType)
+
+// Convert between one type and all other types
+#define CONVERT_BETWEEN_ALL_TYPES(TYPE, ID) \
+  CONVERT_BETWEEN_FLOATS(TYPE, ID)  \
+  CONVERT_BETWEEN_INTEGRALS(TYPE, ID)   \
+  CONVERT_BETWEEN_FIXED_POINT(TYPE, ID)
+
+#define CONVERT_FIXED_POINT_TYPE_WITH_SAT(TYPE, ID) \
+  CONVERT_BETWEEN_ALL_TYPES(TYPE, ID)   \
+  CONVERT_BETWEEN_ALL_TYPES(_Sat TYPE, Sat##ID)
+
+#define CONVERT_FIXED_POINT_TYPE(TYPE, ID)   \
+  CONVERT_FIXED_POINT_TYPE_WITH_SAT(TYPE, ID)\
+  CONVERT_FIXED_POINT_TYPE_WITH_SAT(signed TYPE, Signed##ID) \
+  CONVERT_FIXED_POINT_TYPE_WITH_SAT(unsigned TYPE, Unsigned##ID)
+
+CONVERT_FIXED_POINT_TYPE(short _Fract, ShortFract);
+CONVERT_FIXED_POINT_TYPE(_Fract, Fract);
+CONVERT_FIXED_POINT_TYPE(long _Fract, LongFract);
+
+CONVERT_FIXED_POINT_TYPE(short _Accum, ShortAccum);
+CONVERT_FIXED_POINT_TYPE(_Accum, Accum);
+CONVERT_FIXED_POINT_TYPE(long _Accum, LongAccum);
Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp
===
--- lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -323,6 +323,8 @@
 switch (CastE->getCastKind()) {
   case CK_FixedPointCast:
 llvm_unreachable("CK_FixedPointCast");  // TODO
+  case CK_FloatingToFixedPoint:
+llvm_unreachable("CK_FloatingToFixedPoint");
   case CK_IntegralToFixedPoint:
 llvm_unreachable(
 "ExprEngine::VisitCast CK_IntegralToFixedPoint");  // TODO
Index: 

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-22 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 148025.

Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -542,6 +548,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/accum_errors.cpp
===
--- /dev/null
+++ test/Frontend/accum_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned _Accum u_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+
+short _Accum short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+_Accum accum; // expected-error{{Fixed point types are only allowed in C}}
+long _Accum long_accum;  // expected-error{{Fixed point types are only allowed in C}}
Index: test/Frontend/accum_errors.c
===
--- /dev/null
+++ test/Frontend/accum_errors.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
Index: test/Frontend/accum.c
===
--- /dev/null
+++ test/Frontend/accum.c
@@ -0,0 +1,26 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+/*  Various contexts where type _Accum can appear. */
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+
+// CHECK:  |-VarDecl {{.*}} s_short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum'
+// CHECK-NEXT: `-VarDecl {{.*}} long_accum 'long _Accum'
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -6816,6 +6816,24 @@
 case PREDEF_TYPE_LONGDOUBLE_ID:
   T = Context.LongDoubleTy;
   break;
+case PREDEF_TYPE_SHORT_ACCUM_ID:
+  T = Context.ShortAccumTy;
+  break;
+case PREDEF_TYPE_ACCUM_ID:
+  T = Context.AccumTy;
+  break;
+case PREDEF_TYPE_LONG_ACCUM_ID:
+  T = Context.LongAccumTy;
+  break;
+case PREDEF_TYPE_USHORT_ACCUM_ID:

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-22 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan marked 2 inline comments as done.
leonardchan added inline comments.



Comment at: lib/Index/USRGeneration.cpp:731
+
+  if (c == '~') {
+switch (BT->getKind()) {

jakehehrlich wrote:
> You can make the 'c' a Twine instead. That will let you inline these in their 
> respective locations as `  c = "~UA" ` for instance.
So Twine also isn't assignable. If I still want to keep the pattern of 
assigning to a temporary variable, I could instead just make `c` a string.


Repository:
  rC Clang

https://reviews.llvm.org/D46084



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D46986: [Fixed Point Arithmetic] Validation Test for Fixed Point Binary Operations and Saturated Addition

2018-05-22 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 148116.
leonardchan added a comment.

- formatting
- Running `lli` threw a segfault in the test, though this was probably because 
it was using whatever hist jit was available to optimize the code instead of 
just interpreting it. Forcing it just interpret fixes this.


Repository:
  rC Clang

https://reviews.llvm.org/D46986

Files:
  include/clang/AST/Type.h
  include/clang/Basic/FixedPoint.h.in
  lib/AST/Type.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Sema/SemaExpr.cpp
  test/Frontend/fixed_point_all_builtin_operations.c
  test/Frontend/fixed_point_builtin_macros.c

Index: test/Frontend/fixed_point_builtin_macros.c
===
--- test/Frontend/fixed_point_builtin_macros.c
+++ test/Frontend/fixed_point_builtin_macros.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -S -emit-llvm -o - %s | lli
+// RUN: %clang_cc1 -S -emit-llvm -o - %s | lli -force-interpreter=true
 
 #define assert(b) if (!(b)) { return 1; }
 
Index: test/Frontend/fixed_point_all_builtin_operations.c
===
--- test/Frontend/fixed_point_all_builtin_operations.c
+++ test/Frontend/fixed_point_all_builtin_operations.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -Werror %s
+// RUN: %clang_cc1 -Werror -S -emit-llvm %s -o - | lli -force-interpreter=true
 
 // Check that we can use all supported binary and unary operations according to
 // clause 4.1.6 in N1169.
@@ -66,3 +66,60 @@
 ALL_OPERATIONS(short _Accum, ShortAccum);
 ALL_OPERATIONS(_Accum, Accum);
 ALL_OPERATIONS(long _Accum, LongAccum);
+
+#define ASSERT(x) \
+  if (!(x)) return 1;
+
+#define BINARY_OPS_FOR_TYPE(TYPE, ID, SUFFIX) \
+  {   \
+TYPE a = 0.5##SUFFIX; \
+TYPE b = 0.25##SUFFIX;\
+ASSERT(add##ID(a, b) == 0.75##SUFFIX);\
+ASSERT(sub##ID(a, b) == 0.25##SUFFIX);\
+ASSERT(mul##ID(a, b) == 0.125##SUFFIX);   \
+ASSERT(div##ID(b, a) == 0.5##SUFFIX); \
+ASSERT(shl##ID(b, 1) == a);   \
+ASSERT(shr##ID(a, 1) == b);   \
+ASSERT(lt##ID(b, a)); \
+ASSERT(le##ID(b, a)); \
+ASSERT(gt##ID(a, b)); \
+ASSERT(ge##ID(a, b)); \
+ASSERT(eq##ID(a, b) == 0);\
+ASSERT(ne##ID(a, b)); \
+ASSERT(augmented_add##ID(a, b) == 0.75##SUFFIX);  \
+ASSERT(augmented_sub##ID(a, b) == 0.25##SUFFIX);  \
+ASSERT(augmented_mul##ID(a, b) == 0.125##SUFFIX); \
+ASSERT(augmented_div##ID(b, a) == 0.5##SUFFIX);   \
+ASSERT(augmented_shl##ID(b, 1) == a); \
+ASSERT(augmented_shr##ID(a, 1) == b); \
+  }
+
+#define BINARY_OPS(TYPE, ID, SUFFIX)\
+  BINARY_OPS_FOR_TYPE(TYPE, ID, SUFFIX);\
+  BINARY_OPS_FOR_TYPE(signed TYPE, Signed##ID, SUFFIX); \
+  BINARY_OPS_FOR_TYPE(unsigned TYPE, Unsigned##ID, u##SUFFIX);  \
+  BINARY_OPS_FOR_TYPE(_Sat TYPE, Sat##ID, SUFFIX);  \
+  BINARY_OPS_FOR_TYPE(_Sat signed TYPE, SatSigned##ID, SUFFIX); \
+  BINARY_OPS_FOR_TYPE(_Sat unsigned TYPE, SatUnsigned##ID, u##SUFFIX);
+
+#define FRACT_SAT_BINARY_OPS(TYPE, ID, SUFFIX) \
+  {\
+TYPE a = 0.7##SUFFIX;  \
+TYPE b = 0.9##SUFFIX;  \
+ASSERT(add##ID(a, b) == 1.0##SUFFIX);  \
+  }
+
+int main() {
+  BINARY_OPS(short _Fract, ShortFract, hr);
+  BINARY_OPS(_Fract, Fract, r);
+  BINARY_OPS(long _Fract, LongFract, lr);
+  BINARY_OPS(short _Accum, ShortAccum, hk);
+  BINARY_OPS(_Accum, Accum, k);
+  BINARY_OPS(long _Accum, LongAccum, lk);
+
+  FRACT_SAT_BINARY_OPS(_Sat short _Fract, SatShortFract, hr);
+  FRACT_SAT_BINARY_OPS(_Sat _Fract, SatFract, r);
+  FRACT_SAT_BINARY_OPS(_Sat long _Fract, SatLongFract, lr);
+
+  return 0;
+}
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -1258,8 +1258,12 @@
   return FixedPointTy;
 }
 
-/// \brief Handle arithmethic conversion with fixed point types.  Helper
-/// function of UsualArithmeticConversions().
+/// \brief Handle arithmethic conversion with fixed point types. The usual
+/// arithmetic conversions do not apply to fixed point type conversions between
+/// integers or other fixed point types due to potential loss of precision.
+/// For this case of fixed point types, the resulting type in a binary operation
+/// does not need to be exactly one of the 2 operand types.
+/// Implemented according to Clause 6.3.1.8 of ISO/IEC JTC1 SC22 WG14 N1169.
 static QualType handleFixedPointConversion(Sema &S, ExprResult &LHS,
 

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-22 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 148117.
leonardchan marked an inline comment as done.

Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -542,6 +548,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/accum_errors.cpp
===
--- /dev/null
+++ test/Frontend/accum_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned _Accum u_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+
+short _Accum short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+_Accum accum; // expected-error{{Fixed point types are only allowed in C}}
+long _Accum long_accum;  // expected-error{{Fixed point types are only allowed in C}}
Index: test/Frontend/accum_errors.c
===
--- /dev/null
+++ test/Frontend/accum_errors.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
Index: test/Frontend/accum.c
===
--- /dev/null
+++ test/Frontend/accum.c
@@ -0,0 +1,26 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+/*  Various contexts where type _Accum can appear. */
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+
+// CHECK:  |-VarDecl {{.*}} s_short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum'
+// CHECK-NEXT: `-VarDecl {{.*}} long_accum 'long _Accum'
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -6816,6 +6816,24 @@
 case PREDEF_TYPE_LONGDOUBLE_ID:
   T = Context.LongDoubleTy;
   break;
+case PREDEF_TYPE_SHORT_ACCUM_ID:
+  T = Context.ShortAccumTy;
+  break;
+case PREDEF_TYPE_ACCUM_ID:
+  T = Context.AccumTy;
+  break;
+case PREDEF_TYPE_LONG_ACCUM_ID:
+  T = Context.LongAccumTy;
+  

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-22 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 148121.

Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -542,6 +548,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/accum_errors.cpp
===
--- /dev/null
+++ test/Frontend/accum_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned _Accum u_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+
+short _Accum short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+_Accum accum; // expected-error{{Fixed point types are only allowed in C}}
+long _Accum long_accum;  // expected-error{{Fixed point types are only allowed in C}}
Index: test/Frontend/accum_errors.c
===
--- /dev/null
+++ test/Frontend/accum_errors.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
Index: test/Frontend/accum.c
===
--- /dev/null
+++ test/Frontend/accum.c
@@ -0,0 +1,26 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+/*  Various contexts where type _Accum can appear. */
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+
+// CHECK:  |-VarDecl {{.*}} s_short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum'
+// CHECK-NEXT: `-VarDecl {{.*}} long_accum 'long _Accum'
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -6816,6 +6816,24 @@
 case PREDEF_TYPE_LONGDOUBLE_ID:
   T = Context.LongDoubleTy;
   break;
+case PREDEF_TYPE_SHORT_ACCUM_ID:
+  T = Context.ShortAccumTy;
+  break;
+case PREDEF_TYPE_ACCUM_ID:
+  T = Context.AccumTy;
+  break;
+case PREDEF_TYPE_LONG_ACCUM_ID:
+  T = Context.LongAccumTy;
+  break;
+case PREDEF_TYPE_USHORT_ACCUM_ID:

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-22 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 148148.
leonardchan added a comment.

pulled changes from source tree


Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -546,6 +552,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/accum_errors.cpp
===
--- /dev/null
+++ test/Frontend/accum_errors.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -x c++ %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{Fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned _Accum u_accum;  // expected-error{{Fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{Fixed point types are only allowed in C}}
+
+short _Accum short_accum;  // expected-error{{Fixed point types are only allowed in C}}
+_Accum accum; // expected-error{{Fixed point types are only allowed in C}}
+long _Accum long_accum;  // expected-error{{Fixed point types are only allowed in C}}
Index: test/Frontend/accum_errors.c
===
--- /dev/null
+++ test/Frontend/accum_errors.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s
+
+long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+unsigned long long _Accum u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
Index: test/Frontend/accum.c
===
--- /dev/null
+++ test/Frontend/accum.c
@@ -0,0 +1,26 @@
+// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace
+
+/*  Various contexts where type _Accum can appear. */
+
+// Primary fixed point types
+signed short _Accum s_short_accum;
+signed _Accum s_accum;
+signed long _Accum s_long_accum;
+unsigned short _Accum u_short_accum;
+unsigned _Accum u_accum;
+unsigned long _Accum u_long_accum;
+
+// Aliased fixed point types
+short _Accum short_accum;
+_Accum accum;
+long _Accum long_accum;
+
+// CHECK:  |-VarDecl {{.*}} s_short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum'
+// CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum'
+// CHECK-NEXT: `-VarDecl {{.*}} long_accum 'long _Accum'
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -6818,6 +6818,24 @@
 case PREDEF_TYPE_LONGDOUBLE_ID:
   T = Context.LongDoubleTy;
   break;
+case PREDEF_TYPE_SHORT_ACCUM_ID:
+  T = Context.ShortAccumTy;
+  break;
+case PREDEF_TYPE_ACCUM_ID:
+  T = Context.AccumTy;
+  break;
+case PREDEF_TYPE_LONG_ACCUM_ID:
+  T = Context.Lon

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-23 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a subscriber: sammccall.
leonardchan added inline comments.



Comment at: include/clang/Basic/DiagnosticCommonKinds.td:172
+def err_fixed_point_only_allowed_in_c : Error<
+  "Fixed point types are only allowed in C">;
 

rsmith wrote:
> Diagnostics should not be capitalized. Also, we generally allow conforming C 
> extensions to be used in other languages unless there is a really good reason 
> not to.
We decided not to allow fixed point types in other languages because there is 
no specification provided in N1169 for addressing some features in other 
languages. Using C++ as an example, N1169 does not provide recommended 
characters when name mangling so we do not allow this in C++.



Comment at: lib/AST/ItaniumMangle.cpp:2552
+  case BuiltinType::ULongAccum:
+llvm_unreachable("Fixed point types are disabled for c++");
   case BuiltinType::Half:

rsmith wrote:
> Please check what GCC uses to mangle these, and follow suit; if GCC doesn't 
> have a mangling, you can use a vendor mangling (`u6_Accum`) or produce an 
> error for now, but please open an issue at 
> https://github.com/itanium-cxx-abi/cxx-abi/ to pick a real mangling.
It seems that GCC uses the characters for each fixed point type's corresponding 
integral type (https://github.com/gcc-mirror/gcc/blob/master/gcc/cp/mangle.c). 
Will follow up on this if we end up enabling fixed point types for C++.



Comment at: lib/CodeGen/CGDebugInfo.cpp:678-681
+  case BuiltinType::UShortAccum:
+  case BuiltinType::UAccum:
+  case BuiltinType::ULongAccum:
 Encoding = llvm::dwarf::DW_ATE_unsigned;

rsmith wrote:
> @echristo @dblaikie Is this appropriate?
My bad, this should be changed to `DW_ATE_signed_fixed` and 
`DW_ATE_unsigned_fixed`



Comment at: lib/Index/USRGeneration.cpp:691
+case BuiltinType::ULongAccum:
+  llvm_unreachable("No USR name mangling for fixed point types.");
 case BuiltinType::Float16:

rsmith wrote:
> leonardchan wrote:
> > phosek wrote:
> > > We need some solution for fixed point types.
> > Added character ~ to indicate fixed point type followed by string detailing 
> > the type. I have not added a test to it because logically, I do not think 
> > we will ever reach that point. This logic is implemented in the VisitType 
> > method, which mostly gets called by visitors to c++ nodes like 
> > VisitTemplateParameterList, but we have disabled the use of fixed point 
> > types in c++. VisitType does get called in VisitFunctionDecl but the 
> > function exits early since we are not reading c++ (line 
> > lib/Index/USRGeneration.cpp:238).
> @rjmccall Is this an acceptable USR encoding? (Is our USR encoding scheme 
> documented anywhere?)
I chatted with @sammccall about this who said it was ok to add these types if 
no one opposed this. I posted this on cfe-dev also and it seemed that no one 
spoke up about it, so I thought this was ok.

I also couldn't find any standard or documentation about reserving characters 
for USR. It doesn't seem that USR is also parsed in any way, so I don't think 
I'm breaking anything (running ninja check-all passes).

And unless we also do enable this for C++, this code actually may not be run 
since this method will not be visited if limited to C.


Repository:
  rC Clang

https://reviews.llvm.org/D46084



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-23 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: include/clang/Basic/DiagnosticCommonKinds.td:172
+def err_fixed_point_only_allowed_in_c : Error<
+  "Fixed point types are only allowed in C">;
 

leonardchan wrote:
> rsmith wrote:
> > Diagnostics should not be capitalized. Also, we generally allow conforming 
> > C extensions to be used in other languages unless there is a really good 
> > reason not to.
> We decided not to allow fixed point types in other languages because there is 
> no specification provided in N1169 for addressing some features in other 
> languages. Using C++ as an example, N1169 does not provide recommended 
> characters when name mangling so we do not allow this in C++.
Actually, scratch that. We will be enabling it since GCC does. Will update this 
and other relevant C++ related code appropriately.


Repository:
  rC Clang

https://reviews.llvm.org/D46084



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-23 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: include/clang/Basic/DiagnosticCommonKinds.td:172
+def err_fixed_point_only_allowed_in_c : Error<
+  "Fixed point types are only allowed in C">;
 

leonardchan wrote:
> leonardchan wrote:
> > rsmith wrote:
> > > Diagnostics should not be capitalized. Also, we generally allow 
> > > conforming C extensions to be used in other languages unless there is a 
> > > really good reason not to.
> > We decided not to allow fixed point types in other languages because there 
> > is no specification provided in N1169 for addressing some features in other 
> > languages. Using C++ as an example, N1169 does not provide recommended 
> > characters when name mangling so we do not allow this in C++.
> Actually, scratch that. We will be enabling it since GCC does. Will update 
> this and other relevant C++ related code appropriately.
Actually, the main thing that was preventing us from allowing this in C++ was 
no standardized characters for name mangling. GCC seems to use the same 
characters as some integral types (`short _Accum` uses `s`, `_Accum` uses `i`, 
...) but this would mean that a function that takes a `short _Accum` as a sole 
argument would also be mangled the same as a similarly named function that 
takes a `short`.

Would copying GCC take priority over not having characters specific for these 
types? This standard also proposes 24 different types, of which only 6 are 
included in this patch.


Repository:
  rC Clang

https://reviews.llvm.org/D46084



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-23 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a comment.

After further discussion, we think the best approach for now would be only 
supporting fixed point types in C, then go back and support C++ once there is a 
standardized way for mangling the fixed point types under itanium.


Repository:
  rC Clang

https://reviews.llvm.org/D46084



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-24 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 148445.
leonardchan added a comment.

- Reverted changes involving name mangling since we will only support c++ for 
now. Will concurrently raise an issue on 
https://github.com/itanium-cxx-abi/cxx-abi/ to get characters for name mangling.
- Added a flag that needs to be provided to enable usage of fixed point types. 
Not including this flag and using fixed point types throws an error. Currently, 
this patch allows for these types to be used in all versions of C, but this can 
be narrowed down to specific versions of C.
- An error is thrown when using fixed point types in C++.
- Fixed point types are ignored during USRGeneration since the type only gets 
mangled in C++.
- Fixed point types their own width and alignment accessors/variables in 
TargetInfo.
- Updated debug info to use `DW_ATE_signed_fixed` and `DW_ATE_unsigned_fixed`.
- Added tests mixing _Accum with other type specifiers


Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/LangOptions.def
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TargetInfo.h
  include/clang/Basic/TokenKinds.def
  include/clang/Driver/Options.td
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/Basic/TargetInfo.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_errors.cpp
  test/Frontend/fixed_point_not_enabled.c
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -546,6 +552,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/fixed_point_not_enabled.c
===
--- /dev/null
+++ test/Frontend/fixed_point_not_enabled.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -x c -verify %s
+
+// Primary fixed point types
+signed short _Accum s_short_accum;// expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+signed _Accum s_accum;// expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+signed long _Accum s_long_accum;  // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+unsigned short _Accum u_short_accum;  // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+unsigned _Accum u_accum;  // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+unsigned long _Accum u_long_accum;// expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+
+// Aliased fixed point types
+short _Accum short_accum; // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+_Accum accum; // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+  // expected-warning@-1{{type specifier missing, defaults to 'int'}}
+long _Accum long_accum;   // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
Index: test/Frontend/fixed_point_errors.cpp
===
--- /dev/null
+++ test/Frontend/fixed_point_errors.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -x c++ -enable-fixed-point %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;// expected-e

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-24 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan marked 6 inline comments as done.
leonardchan added inline comments.



Comment at: lib/CodeGen/ItaniumCXXABI.cpp:2684
 
   // Types added here must also be added to EmitFundamentalRTTIDescriptors.
   switch (Ty->getKind()) {

rsmith wrote:
> Note this comment :)
Returned false for these types now. Not sure if these types should also be 
added to EmitFundamentalRTTIDescriptors since the OCL types do not appear under 
there.


Repository:
  rC Clang

https://reviews.llvm.org/D46084



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-24 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 148452.

Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/LangOptions.def
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TargetInfo.h
  include/clang/Basic/TokenKinds.def
  include/clang/Driver/Options.td
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/Basic/TargetInfo.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_errors.cpp
  test/Frontend/fixed_point_not_enabled.c
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -546,6 +552,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/fixed_point_not_enabled.c
===
--- /dev/null
+++ test/Frontend/fixed_point_not_enabled.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -x c -verify %s
+
+// Primary fixed point types
+signed short _Accum s_short_accum;// expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+signed _Accum s_accum;// expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+signed long _Accum s_long_accum;  // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+unsigned short _Accum u_short_accum;  // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+unsigned _Accum u_accum;  // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+unsigned long _Accum u_long_accum;// expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+
+// Aliased fixed point types
+short _Accum short_accum; // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+_Accum accum; // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+  // expected-warning@-1{{type specifier missing, defaults to 'int'}}
+long _Accum long_accum;   // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
Index: test/Frontend/fixed_point_errors.cpp
===
--- /dev/null
+++ test/Frontend/fixed_point_errors.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -x c++ -enable-fixed-point %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;// expected-error{{fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;// expected-error{{fixed point types are only allowed in C}}
+unsigned _Accum u_accum;// expected-error{{fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{fixed point types are only allowed in C}}
+
+short _Accum short_accum;   // expected-error{{fixed point types are only allowed in C}}
+_Accum accum;   // expected-error{{fixed point types are only allowed in C}}
+// expected-error@-1{{C++ requires a type specifier for all declarations}}
+long _Accum long_accum; // expected-error{{fixed point types are only allowed in C}}
Index: test/Frontend/fixed_point_errors.c
===
--- 

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-24 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 148481.
leonardchan marked 2 inline comments as done.
leonardchan added a comment.

- Added test case for `_Bool _Accum`
- Getters for the `_Accum` bit widths return values for their corresponding 
integral types (ie. `sizeof(short _Accum) == sizeof(short)`). The only case 
where this may not happen is if the target architecture uses 16 bits for an 
int. N1169 requires that a `signed/unsigned _Accum` hold at least 15 fractional 
bits and 4 integral bits. To be able to fit these bits, the size is upgraded to 
that of a long which is guaranteed to be large enough to hold them.


Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/LangOptions.def
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TargetInfo.h
  include/clang/Basic/TokenKinds.def
  include/clang/Driver/Options.td
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_bit_widths.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_errors.cpp
  test/Frontend/fixed_point_not_enabled.c
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -546,6 +552,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/fixed_point_not_enabled.c
===
--- /dev/null
+++ test/Frontend/fixed_point_not_enabled.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -x c -verify %s
+
+// Primary fixed point types
+signed short _Accum s_short_accum;// expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+signed _Accum s_accum;// expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+signed long _Accum s_long_accum;  // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+unsigned short _Accum u_short_accum;  // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+unsigned _Accum u_accum;  // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+unsigned long _Accum u_long_accum;// expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+
+// Aliased fixed point types
+short _Accum short_accum; // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+_Accum accum; // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+  // expected-warning@-1{{type specifier missing, defaults to 'int'}}
+long _Accum long_accum;   // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
Index: test/Frontend/fixed_point_errors.cpp
===
--- /dev/null
+++ test/Frontend/fixed_point_errors.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -x c++ -enable-fixed-point %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;// expected-error{{fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;// expected-error{{fixed point types are only allowed in C}}
+unsigned _Accum u_accum;// expected-error{{fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expecte

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-24 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a comment.

In https://reviews.llvm.org/D46084#374, @jfb wrote:

> Can you also add a test for `_Bool _Accum`.
>
> Also, `-enable-fixed-point -x c++` failing.


.
Done. Also the failing c++ case is under `test/Frontend/fixed_point_errors.cpp`


Repository:
  rC Clang

https://reviews.llvm.org/D46084



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-24 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 148506.
leonardchan added a comment.

Re-added individual getters/members for _Accum types


Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/LangOptions.def
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TargetInfo.h
  include/clang/Basic/TokenKinds.def
  include/clang/Driver/Options.td
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/Basic/TargetInfo.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_bit_widths.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_errors.cpp
  test/Frontend/fixed_point_not_enabled.c
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -546,6 +552,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/fixed_point_not_enabled.c
===
--- /dev/null
+++ test/Frontend/fixed_point_not_enabled.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -x c -verify %s
+
+// Primary fixed point types
+signed short _Accum s_short_accum;// expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+signed _Accum s_accum;// expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+signed long _Accum s_long_accum;  // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+unsigned short _Accum u_short_accum;  // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+unsigned _Accum u_accum;  // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+unsigned long _Accum u_long_accum;// expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+
+// Aliased fixed point types
+short _Accum short_accum; // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+_Accum accum; // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
+  // expected-warning@-1{{type specifier missing, defaults to 'int'}}
+long _Accum long_accum;   // expected-error{{compile with '-enable-fixed-point' to enable fixed point types}}
Index: test/Frontend/fixed_point_errors.cpp
===
--- /dev/null
+++ test/Frontend/fixed_point_errors.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -x c++ -enable-fixed-point %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;// expected-error{{fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;// expected-error{{fixed point types are only allowed in C}}
+unsigned _Accum u_accum;// expected-error{{fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{fixed point types are only allowed in C}}
+
+short _Accum short_accum;   // expected-error{{fixed point types are only allowed in C}}
+_Accum accum;   // expected-error{{fixed point types are only allowed in C}}
+// expected-error@-1{{C++ requires a type specifier for all declarations}}
+long _Accum long_accum; // expected-error{{fixed point types are only allo

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-24 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: include/clang/Basic/TargetInfo.h:382
+// enough bits to fit the minumum.
+if (getIntWidth() < MinSignedAccumDataBits)
+  return getLongWidth();

ebevhan wrote:
> I'm not sure I agree with this interpretation. It's simply not correct to 
> consider 'short' the 'underlying type' of 'short _Accum', 'int' the 
> 'underlying type' of '_Accum', etc. They are wholly independent and should 
> have separate settings altogether.
> 
> Asserting/ensuring that a target has set an invalid width for its types 
> should be done separately. This currently feels a bit like the TargetInfo is 
> guessing.
> 
> (For the record, the reason I'm requesting this change is because this 
> implementation does not work for us downstream.)
You're right. They should be different types. I was stuck in the mindset that 
`short _Accum` should be tied to `short`, `_Accum` be tied to `int`, etc.


Repository:
  rC Clang

https://reviews.llvm.org/D46084



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-25 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 148637.
leonardchan added a comment.

Changed flag names


Repository:
  rC Clang

https://reviews.llvm.org/D46084

Files:
  include/clang-c/Index.h
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/LangOptions.def
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TargetInfo.h
  include/clang/Basic/TokenKinds.def
  include/clang/Driver/Options.td
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/Basic/TargetInfo.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_bit_widths.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_errors.cpp
  test/Frontend/fixed_point_not_enabled.c
  tools/libclang/CXType.cpp

Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -53,6 +53,12 @@
 BTCASE(Float);
 BTCASE(Double);
 BTCASE(LongDouble);
+BTCASE(ShortAccum);
+BTCASE(Accum);
+BTCASE(LongAccum);
+BTCASE(UShortAccum);
+BTCASE(UAccum);
+BTCASE(ULongAccum);
 BTCASE(Float16);
 BTCASE(Float128);
 BTCASE(NullPtr);
@@ -546,6 +552,12 @@
 TKIND(Float);
 TKIND(Double);
 TKIND(LongDouble);
+TKIND(ShortAccum);
+TKIND(Accum);
+TKIND(LongAccum);
+TKIND(UShortAccum);
+TKIND(UAccum);
+TKIND(ULongAccum);
 TKIND(Float16);
 TKIND(Float128);
 TKIND(NullPtr);
Index: test/Frontend/fixed_point_not_enabled.c
===
--- /dev/null
+++ test/Frontend/fixed_point_not_enabled.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -x c -verify %s
+// RUN: %clang_cc1 -x c -fno-fixed-point -verify %s
+
+// Primary fixed point types
+signed short _Accum s_short_accum;// expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+signed _Accum s_accum;// expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+signed long _Accum s_long_accum;  // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+unsigned short _Accum u_short_accum;  // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+unsigned _Accum u_accum;  // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+unsigned long _Accum u_long_accum;// expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+
+// Aliased fixed point types
+short _Accum short_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+_Accum accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+  // expected-warning@-1{{type specifier missing, defaults to 'int'}}
+long _Accum long_accum;   // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
Index: test/Frontend/fixed_point_errors.cpp
===
--- /dev/null
+++ test/Frontend/fixed_point_errors.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -x c++ -ffixed-point %s -verify
+
+// Name namgling is not provided for fixed point types in c++
+
+signed short _Accum s_short_accum;  // expected-error{{fixed point types are only allowed in C}}
+signed _Accum s_accum;  // expected-error{{fixed point types are only allowed in C}}
+signed long _Accum s_long_accum;// expected-error{{fixed point types are only allowed in C}}
+unsigned short _Accum u_short_accum;// expected-error{{fixed point types are only allowed in C}}
+unsigned _Accum u_accum;// expected-error{{fixed point types are only allowed in C}}
+unsigned long _Accum u_long_accum;  // expected-error{{fixed point types are only allowed in C}}
+
+short _Accum short_accum;   // expected-error{{fixed point types are only allowed in C}}
+_Accum accum;   // expected-error{{fixed point types are only allowed in C}}
+// expected-error@-1{{C++ requires a type specifier for all declarations}}
+long _Accum long_accum; // expected-error{{fixed point types are only allowed in C}}
Index: test/Frontend/fixed_poi

[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-25 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan marked 2 inline comments as done.
leonardchan added inline comments.



Comment at: include/clang/Driver/Options.td:882
 
+def enable_fixed_point : Flag<["-", "--"], "enable-fixed-point">, 
Group,
+ Flags<[CC1Option]>, HelpText<"Enable fixed point 
types">;

ebevhan wrote:
> Shouldn't this be an `-f` flag, like `-ffixed-point`? I'm not for or against 
> either, just wondering what anyone else thinks.
Makes sense since this flag is target independent.


Repository:
  rC Clang

https://reviews.llvm.org/D46084



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D46911: [Fixed Point Arithmetic] Addition of the remaining fixed point types and their saturated equivalents

2018-05-29 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 148918.
leonardchan marked 4 inline comments as done.

Repository:
  rC Clang

https://reviews.llvm.org/D46911

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/AST/Type.h
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Basic/Specifiers.h
  include/clang/Basic/TargetInfo.h
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/DeclSpec.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/Analysis/PrintfFormatString.cpp
  lib/Basic/TargetInfo.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/SemaTemplateVariadic.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_bit_widths.c
  test/Frontend/fixed_point_errors.c

Index: test/Frontend/fixed_point_errors.c
===
--- test/Frontend/fixed_point_errors.c
+++ test/Frontend/fixed_point_errors.c
@@ -5,6 +5,14 @@
 
 long long _Accum longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
 unsigned long long _Accum u_longlong_accum;   // expected-error{{'long long _Accum' is invalid}}
+long long _Fract longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+unsigned long long _Fract u_longlong_fract;   // expected-error{{'long long _Fract' is invalid}}
+
+_Sat long long _Accum sat_longlong_accum; // expected-error{{'long long _Accum' is invalid}}
+_Sat unsigned long long _Accum sat_u_longlong_accum;  // expected-error{{'long long _Accum' is invalid}}
+_Sat long long _Fract sat_longlong_fract; // expected-error{{'long long _Fract' is invalid}}
+_Sat unsigned long long _Fract sat_u_longlong_fract;  // expected-error{{'long long _Fract' is invalid}}
+
 
 /* Although _Complex types work with floating point numbers, the extension
  * provides no info for complex fixed point types. */
@@ -19,9 +27,53 @@
 _Complex _Accum cmplx_s_accum;  // expected-error{{'_Complex _Accum' is invalid}}
 _Complex long _Accum cmplx_s_long_accum;// expected-error{{'_Complex _Accum' is invalid}}
 
+_Complex signed short _Fract cmplx_s_short_fract;   // expected-error{{'_Complex _Fract' is invalid}}
+_Complex signed _Fract cmplx_s_fract;   // expected-error{{'_Complex _Fract' is invalid}}
+_Complex signed long _Fract cmplx_s_long_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex unsigned short _Fract cmplx_u_short_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex unsigned _Fract cmplx_u_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex unsigned long _Fract cmplx_u_long_fract;   // expected-error{{'_Complex _Fract' is invalid}}
+_Complex short _Fract cmplx_s_short_fract;  // expected-error{{'_Complex _Fract' is invalid}}
+_Complex _Fract cmplx_s_fract;  // expected-error{{'_Complex _Fract' is invalid}}
+_Complex long _Fract cmplx_s_long_fract;// expected-error{{'_Complex _Fract' is invalid}}
+
+_Complex _Sat signed short _Accum cmplx_sat_s_short_accum;   // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat signed _Accum cmplx_sat_s_accum;   // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat signed long _Accum cmplx_sat_s_long_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat unsigned short _Accum cmplx_sat_u_short_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat unsigned _Accum cmplx_sat_u_accum; // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat unsigned long _Accum cmplx_sat_u_long_accum;   // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat short _Accum cmplx_sat_s_short_accum;  // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat _Accum cmplx_sat_s_accum;  // expected-error{{'_Complex _Accum' is invalid}}
+_Complex _Sat long _Accum cmplx_sat_s_long_accum;// expected-error{{'_Complex _Accum' is invalid}}
+
+_Complex signed short _Fract cmplx_sat_s_short_fract;   // expected-error{{'_Complex _Fract' is invalid}}
+_Complex signed _Fract cmplx_sat_s_fract;   // expected-error{{'_Complex _Fract' is invalid}}
+_Complex signed long _Fract cmplx_sat_s_long_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex unsigned short _Fract cmplx_sat_u_short_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Complex unsigned _Fract cmplx_sat_u_fract; // expected-error{{'_Complex _Fract' is invalid}}
+_Comp

[PATCH] D46911: [Fixed Point Arithmetic] Addition of the remaining fixed point types and their saturated equivalents

2018-05-29 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added inline comments.



Comment at: lib/Sema/SemaType.cpp:1430
 } else {
-  switch (DS.getTypeSpecWidth()) {
-case DeclSpec::TSW_short:
-  Result = Context.UnsignedShortAccumTy;
-  break;
-case DeclSpec::TSW_unspecified:
-  Result = Context.UnsignedAccumTy;
-  break;
-case DeclSpec::TSW_long:
-  Result = Context.UnsignedLongAccumTy;
-  break;
-case DeclSpec::TSW_longlong:
-  // TODO: Replace with diag
-  llvm_unreachable("Unable to specify long long as _Accum width");
-  break;
+  if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
+switch (DS.getTypeSpecWidth()) {

ebevhan wrote:
> You should probably use the 'getCorrespondingSaturatingType' function instead 
> of disambiguating the whole thing here again.
Also used getCorrespondingSignedType() for the signage


Repository:
  rC Clang

https://reviews.llvm.org/D46911



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D46084: [Fixed Point Arithmetic] Addition of the Fixed Point _Accum type

2018-05-29 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a comment.

Hi all, I think I've addressed all comments on this patch and will be 
committing tomorrow morning unless anyone has any more comments they'd like to 
bring up.


Repository:
  rC Clang

https://reviews.llvm.org/D46084



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D51229: [Sema/Attribute] Make types declared with address_space an AttributedType

2018-08-24 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: rjmccall, rsmith, phosek, mcgrathr, ebevhan, 
theraven.
leonardchan added a project: clang.

Currently an address_space is stored in a qualifier. This makes any type 
declared with an address_space attribute in the form 
`__attribute__((address_space(1))) int 1;` be wrapped in an AttributedType.

This is for a later patch where if `address_space` is declared in a macro, any 
diagnostics that would normally print the address space will instead dump the 
macro name. This will require saving any macro information in the 
AttributedType.


Repository:
  rC Clang

https://reviews.llvm.org/D51229

Files:
  include/clang/Basic/Attr.td
  lib/AST/TypePrinter.cpp
  lib/Sema/SemaType.cpp


Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -7281,10 +7281,21 @@
 case ParsedAttr::AT_OpenCLLocalAddressSpace:
 case ParsedAttr::AT_OpenCLConstantAddressSpace:
 case ParsedAttr::AT_OpenCLGenericAddressSpace:
-case ParsedAttr::AT_AddressSpace:
+case ParsedAttr::AT_AddressSpace: {
   HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
+
+  if (attr.getKind() == ParsedAttr::AT_AddressSpace &&
+  !type->getAs()) {
+ASTContext &Ctx = state.getSema().Context;
+auto *ASAttr = ::new (Ctx) AddressSpaceAttr(
+attr.getRange(), Ctx, attr.getAttributeSpellingListIndex(),
+static_cast(type.getQualifiers().getAddressSpace()));
+type = state.getAttributedType(ASAttr, type, type);
+  }
+
   attr.setUsedAsTypeAttr();
   break;
+}
 OBJC_POINTER_TYPE_ATTRS_CASELIST:
   if (!handleObjCPointerTypeAttr(state, attr, type))
 distributeObjCPointerTypeAttr(state, attr, type);
Index: lib/AST/TypePrinter.cpp
===
--- lib/AST/TypePrinter.cpp
+++ lib/AST/TypePrinter.cpp
@@ -1427,6 +1427,9 @@
 return;
   }
 
+  if (T->getAttrKind() == attr::AddressSpace)
+return;
+
   OS << " __attribute__((";
   switch (T->getAttrKind()) {
 #define TYPE_ATTR(NAME)
@@ -1494,6 +1497,9 @@
   case attr::PreserveAll:
 OS << "preserve_all";
 break;
+
+  case attr::AddressSpace:
+llvm_unreachable("Printing of address_space is handled by the qualifier");
   }
   OS << "))";
 }
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -564,8 +564,6 @@
   let Spellings = [Clang<"address_space">];
   let Args = [IntArgument<"AddressSpace">];
   let Documentation = [Undocumented];
-  // Represented as a qualifier or DependentAddressSpaceType instead.
-  let ASTNode = 0;
 }
 
 def Alias : Attr {


Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -7281,10 +7281,21 @@
 case ParsedAttr::AT_OpenCLLocalAddressSpace:
 case ParsedAttr::AT_OpenCLConstantAddressSpace:
 case ParsedAttr::AT_OpenCLGenericAddressSpace:
-case ParsedAttr::AT_AddressSpace:
+case ParsedAttr::AT_AddressSpace: {
   HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
+
+  if (attr.getKind() == ParsedAttr::AT_AddressSpace &&
+  !type->getAs()) {
+ASTContext &Ctx = state.getSema().Context;
+auto *ASAttr = ::new (Ctx) AddressSpaceAttr(
+attr.getRange(), Ctx, attr.getAttributeSpellingListIndex(),
+static_cast(type.getQualifiers().getAddressSpace()));
+type = state.getAttributedType(ASAttr, type, type);
+  }
+
   attr.setUsedAsTypeAttr();
   break;
+}
 OBJC_POINTER_TYPE_ATTRS_CASELIST:
   if (!handleObjCPointerTypeAttr(state, attr, type))
 distributeObjCPointerTypeAttr(state, attr, type);
Index: lib/AST/TypePrinter.cpp
===
--- lib/AST/TypePrinter.cpp
+++ lib/AST/TypePrinter.cpp
@@ -1427,6 +1427,9 @@
 return;
   }
 
+  if (T->getAttrKind() == attr::AddressSpace)
+return;
+
   OS << " __attribute__((";
   switch (T->getAttrKind()) {
 #define TYPE_ATTR(NAME)
@@ -1494,6 +1497,9 @@
   case attr::PreserveAll:
 OS << "preserve_all";
 break;
+
+  case attr::AddressSpace:
+llvm_unreachable("Printing of address_space is handled by the qualifier");
   }
   OS << "))";
 }
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -564,8 +564,6 @@
   let Spellings = [Clang<"address_space">];
   let Args = [IntArgument<"AddressSpace">];
   let Documentation = [Undocumented];
-  // Represented as a qualifier or DependentAddressSpaceType instead.
-  let ASTNode = 0;
 }
 
 def Alias : Attr {
___
cfe-commits

[PATCH] D49511: [Sema/Attribute] Check for noderef attribute

2018-08-24 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan added a comment.

@rsmith ping


Repository:
  rC Clang

https://reviews.llvm.org/D49511



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D51229: [Sema/Attribute] Make types declared with address_space an AttributedType

2018-08-24 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 162487.
leonardchan marked 3 inline comments as done.

Repository:
  rC Clang

https://reviews.llvm.org/D51229

Files:
  include/clang/Basic/Attr.td
  lib/AST/TypePrinter.cpp
  lib/Sema/SemaType.cpp


Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -5767,7 +5767,10 @@
 /// specified type.  The attribute contains 1 argument, the id of the address
 /// space for the type.
 static void HandleAddressSpaceTypeAttribute(QualType &Type,
-const ParsedAttr &Attr, Sema &S) {
+const ParsedAttr &Attr,
+TypeProcessingState &State) {
+  Sema &S = State.getSema();
+
   // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be
   // qualified by an address-space qualifier."
   if (Type->isFunctionType()) {
@@ -5809,10 +5812,18 @@
 // the type.
 QualType T = S.BuildAddressSpaceAttr(Type, ASArgExpr, Attr.getLoc());
 
-if (!T.isNull())
+if (!T.isNull()) {
+  if (!T->getAs()) {
+ASTContext &Ctx = S.Context;
+auto *ASAttr = ::new (Ctx) AddressSpaceAttr(
+Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(),
+static_cast(T.getQualifiers().getAddressSpace()));
+T = State.getAttributedType(ASAttr, T, T);
+  }
   Type = T;
-else
+} else {
   Attr.setInvalid();
+}
   } else {
 // The keyword-based type attributes imply which address space to use.
 switch (Attr.getKind()) {
@@ -7282,7 +7293,7 @@
 case ParsedAttr::AT_OpenCLConstantAddressSpace:
 case ParsedAttr::AT_OpenCLGenericAddressSpace:
 case ParsedAttr::AT_AddressSpace:
-  HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
+  HandleAddressSpaceTypeAttribute(type, attr, state);
   attr.setUsedAsTypeAttr();
   break;
 OBJC_POINTER_TYPE_ATTRS_CASELIST:
Index: lib/AST/TypePrinter.cpp
===
--- lib/AST/TypePrinter.cpp
+++ lib/AST/TypePrinter.cpp
@@ -1427,6 +1427,12 @@
 return;
   }
 
+  // The printing of the address_space attribute is handled by the qualifier
+  // since it is still stored in the qualifier. Return early to prevent 
printing
+  // this twice.
+  if (T->getAttrKind() == attr::AddressSpace)
+return;
+
   OS << " __attribute__((";
   switch (T->getAttrKind()) {
 #define TYPE_ATTR(NAME)
@@ -1456,6 +1462,7 @@
   case attr::Ptr64:
   case attr::SPtr:
   case attr::UPtr:
+  case attr::AddressSpace:
 llvm_unreachable("This attribute should have been handled already");
 
   case attr::NSReturnsRetained:
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -564,8 +564,6 @@
   let Spellings = [Clang<"address_space">];
   let Args = [IntArgument<"AddressSpace">];
   let Documentation = [Undocumented];
-  // Represented as a qualifier or DependentAddressSpaceType instead.
-  let ASTNode = 0;
 }
 
 def Alias : Attr {


Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -5767,7 +5767,10 @@
 /// specified type.  The attribute contains 1 argument, the id of the address
 /// space for the type.
 static void HandleAddressSpaceTypeAttribute(QualType &Type,
-const ParsedAttr &Attr, Sema &S) {
+const ParsedAttr &Attr,
+TypeProcessingState &State) {
+  Sema &S = State.getSema();
+
   // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be
   // qualified by an address-space qualifier."
   if (Type->isFunctionType()) {
@@ -5809,10 +5812,18 @@
 // the type.
 QualType T = S.BuildAddressSpaceAttr(Type, ASArgExpr, Attr.getLoc());
 
-if (!T.isNull())
+if (!T.isNull()) {
+  if (!T->getAs()) {
+ASTContext &Ctx = S.Context;
+auto *ASAttr = ::new (Ctx) AddressSpaceAttr(
+Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(),
+static_cast(T.getQualifiers().getAddressSpace()));
+T = State.getAttributedType(ASAttr, T, T);
+  }
   Type = T;
-else
+} else {
   Attr.setInvalid();
+}
   } else {
 // The keyword-based type attributes imply which address space to use.
 switch (Attr.getKind()) {
@@ -7282,7 +7293,7 @@
 case ParsedAttr::AT_OpenCLConstantAddressSpace:
 case ParsedAttr::AT_OpenCLGenericAddressSpace:
 case ParsedAttr::AT_AddressSpace:
-  HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
+  HandleAddressSpaceTypeAttribute(type, attr, state);
   attr.setUsedAsTypeAttr();
   break;
 

[PATCH] D51229: [Sema/Attribute] Make types declared with address_space an AttributedType

2018-08-24 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 162515.
leonardchan marked an inline comment as done.

Repository:
  rC Clang

https://reviews.llvm.org/D51229

Files:
  include/clang/Basic/Attr.td
  lib/AST/TypePrinter.cpp
  lib/Sema/SemaType.cpp


Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -5615,6 +5615,12 @@
   CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
 }
 
+while (DependentAddressSpaceTypeLoc TL =
+   CurrTL.getAs()) {
+  fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs());
+  CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc();
+}
+
 // FIXME: Ordering here?
 while (AdjustedTypeLoc TL = CurrTL.getAs())
   CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
@@ -5767,7 +5773,10 @@
 /// specified type.  The attribute contains 1 argument, the id of the address
 /// space for the type.
 static void HandleAddressSpaceTypeAttribute(QualType &Type,
-const ParsedAttr &Attr, Sema &S) {
+const ParsedAttr &Attr,
+TypeProcessingState &State) {
+  Sema &S = State.getSema();
+
   // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be
   // qualified by an address-space qualifier."
   if (Type->isFunctionType()) {
@@ -5809,10 +5818,15 @@
 // the type.
 QualType T = S.BuildAddressSpaceAttr(Type, ASArgExpr, Attr.getLoc());
 
-if (!T.isNull())
-  Type = T;
-else
+if (!T.isNull()) {
+  ASTContext &Ctx = S.Context;
+  auto *ASAttr = ::new (Ctx) AddressSpaceAttr(
+  Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(),
+  static_cast(T.getQualifiers().getAddressSpace()));
+  Type = State.getAttributedType(ASAttr, T, T);
+} else {
   Attr.setInvalid();
+}
   } else {
 // The keyword-based type attributes imply which address space to use.
 switch (Attr.getKind()) {
@@ -7282,7 +7296,7 @@
 case ParsedAttr::AT_OpenCLConstantAddressSpace:
 case ParsedAttr::AT_OpenCLGenericAddressSpace:
 case ParsedAttr::AT_AddressSpace:
-  HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
+  HandleAddressSpaceTypeAttribute(type, attr, state);
   attr.setUsedAsTypeAttr();
   break;
 OBJC_POINTER_TYPE_ATTRS_CASELIST:
Index: lib/AST/TypePrinter.cpp
===
--- lib/AST/TypePrinter.cpp
+++ lib/AST/TypePrinter.cpp
@@ -1427,6 +1427,12 @@
 return;
   }
 
+  // The printing of the address_space attribute is handled by the qualifier
+  // since it is still stored in the qualifier. Return early to prevent 
printing
+  // this twice.
+  if (T->getAttrKind() == attr::AddressSpace)
+return;
+
   OS << " __attribute__((";
   switch (T->getAttrKind()) {
 #define TYPE_ATTR(NAME)
@@ -1456,6 +1462,7 @@
   case attr::Ptr64:
   case attr::SPtr:
   case attr::UPtr:
+  case attr::AddressSpace:
 llvm_unreachable("This attribute should have been handled already");
 
   case attr::NSReturnsRetained:
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -564,8 +564,6 @@
   let Spellings = [Clang<"address_space">];
   let Args = [IntArgument<"AddressSpace">];
   let Documentation = [Undocumented];
-  // Represented as a qualifier or DependentAddressSpaceType instead.
-  let ASTNode = 0;
 }
 
 def Alias : Attr {


Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -5615,6 +5615,12 @@
   CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
 }
 
+while (DependentAddressSpaceTypeLoc TL =
+   CurrTL.getAs()) {
+  fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs());
+  CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc();
+}
+
 // FIXME: Ordering here?
 while (AdjustedTypeLoc TL = CurrTL.getAs())
   CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
@@ -5767,7 +5773,10 @@
 /// specified type.  The attribute contains 1 argument, the id of the address
 /// space for the type.
 static void HandleAddressSpaceTypeAttribute(QualType &Type,
-const ParsedAttr &Attr, Sema &S) {
+const ParsedAttr &Attr,
+TypeProcessingState &State) {
+  Sema &S = State.getSema();
+
   // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be
   // qualified by an address-space qualifier."
   if (Type->isFunctionType()) {
@@ -5809,10 +5818,15 @@
 // the type.
 QualType T = S.BuildAddressSpaceAttr(Type, ASArgExpr, Attr.getLoc());
 
-if (!T.isNull())
-  Type = T;

[PATCH] D51229: [Sema/Attribute] Make types declared with address_space an AttributedType

2018-08-27 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan updated this revision to Diff 162711.
leonardchan marked an inline comment as done.

Repository:
  rC Clang

https://reviews.llvm.org/D51229

Files:
  include/clang/Basic/Attr.td
  lib/AST/TypePrinter.cpp
  lib/Sema/SemaType.cpp

Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -5597,12 +5597,6 @@
   }
 
   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
-if (DependentAddressSpaceTypeLoc DASTL =
-CurrTL.getAs()) {
-  fillDependentAddressSpaceTypeLoc(DASTL, D.getTypeObject(i).getAttrs());
-  CurrTL = DASTL.getPointeeTypeLoc().getUnqualifiedLoc();
-}
-
 // An AtomicTypeLoc might be produced by an atomic qualifier in this
 // declarator chunk.
 if (AtomicTypeLoc ATL = CurrTL.getAs()) {
@@ -5615,6 +5609,12 @@
   CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
 }
 
+while (DependentAddressSpaceTypeLoc TL =
+   CurrTL.getAs()) {
+  fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs());
+  CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc();
+}
+
 // FIXME: Ordering here?
 while (AdjustedTypeLoc TL = CurrTL.getAs())
   CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
@@ -5767,7 +5767,10 @@
 /// specified type.  The attribute contains 1 argument, the id of the address
 /// space for the type.
 static void HandleAddressSpaceTypeAttribute(QualType &Type,
-const ParsedAttr &Attr, Sema &S) {
+const ParsedAttr &Attr,
+TypeProcessingState &State) {
+  Sema &S = State.getSema();
+
   // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be
   // qualified by an address-space qualifier."
   if (Type->isFunctionType()) {
@@ -5809,10 +5812,15 @@
 // the type.
 QualType T = S.BuildAddressSpaceAttr(Type, ASArgExpr, Attr.getLoc());
 
-if (!T.isNull())
-  Type = T;
-else
+if (!T.isNull()) {
+  ASTContext &Ctx = S.Context;
+  auto *ASAttr = ::new (Ctx) AddressSpaceAttr(
+  Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(),
+  static_cast(T.getQualifiers().getAddressSpace()));
+  Type = State.getAttributedType(ASAttr, T, T);
+} else {
   Attr.setInvalid();
+}
   } else {
 // The keyword-based type attributes imply which address space to use.
 switch (Attr.getKind()) {
@@ -7282,7 +7290,7 @@
 case ParsedAttr::AT_OpenCLConstantAddressSpace:
 case ParsedAttr::AT_OpenCLGenericAddressSpace:
 case ParsedAttr::AT_AddressSpace:
-  HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
+  HandleAddressSpaceTypeAttribute(type, attr, state);
   attr.setUsedAsTypeAttr();
   break;
 OBJC_POINTER_TYPE_ATTRS_CASELIST:
Index: lib/AST/TypePrinter.cpp
===
--- lib/AST/TypePrinter.cpp
+++ lib/AST/TypePrinter.cpp
@@ -1427,6 +1427,12 @@
 return;
   }
 
+  // The printing of the address_space attribute is handled by the qualifier
+  // since it is still stored in the qualifier. Return early to prevent printing
+  // this twice.
+  if (T->getAttrKind() == attr::AddressSpace)
+return;
+
   OS << " __attribute__((";
   switch (T->getAttrKind()) {
 #define TYPE_ATTR(NAME)
@@ -1456,6 +1462,7 @@
   case attr::Ptr64:
   case attr::SPtr:
   case attr::UPtr:
+  case attr::AddressSpace:
 llvm_unreachable("This attribute should have been handled already");
 
   case attr::NSReturnsRetained:
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -564,8 +564,6 @@
   let Spellings = [Clang<"address_space">];
   let Args = [IntArgument<"AddressSpace">];
   let Documentation = [Undocumented];
-  // Represented as a qualifier or DependentAddressSpaceType instead.
-  let ASTNode = 0;
 }
 
 def Alias : Attr {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D51229: [Sema/Attribute] Make types declared with address_space an AttributedType

2018-08-27 Thread Leonard Chan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC340765: [Sema/Attribute] Make types declared with 
address_space an AttributedType (authored by leonardchan, committed by ).

Repository:
  rC Clang

https://reviews.llvm.org/D51229

Files:
  include/clang/Basic/Attr.td
  lib/AST/TypePrinter.cpp
  lib/Sema/SemaType.cpp

Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -564,8 +564,6 @@
   let Spellings = [Clang<"address_space">];
   let Args = [IntArgument<"AddressSpace">];
   let Documentation = [Undocumented];
-  // Represented as a qualifier or DependentAddressSpaceType instead.
-  let ASTNode = 0;
 }
 
 def Alias : Attr {
Index: lib/AST/TypePrinter.cpp
===
--- lib/AST/TypePrinter.cpp
+++ lib/AST/TypePrinter.cpp
@@ -1427,6 +1427,12 @@
 return;
   }
 
+  // The printing of the address_space attribute is handled by the qualifier
+  // since it is still stored in the qualifier. Return early to prevent printing
+  // this twice.
+  if (T->getAttrKind() == attr::AddressSpace)
+return;
+
   OS << " __attribute__((";
   switch (T->getAttrKind()) {
 #define TYPE_ATTR(NAME)
@@ -1456,6 +1462,7 @@
   case attr::Ptr64:
   case attr::SPtr:
   case attr::UPtr:
+  case attr::AddressSpace:
 llvm_unreachable("This attribute should have been handled already");
 
   case attr::NSReturnsRetained:
Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -5597,12 +5597,6 @@
   }
 
   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
-if (DependentAddressSpaceTypeLoc DASTL =
-CurrTL.getAs()) {
-  fillDependentAddressSpaceTypeLoc(DASTL, D.getTypeObject(i).getAttrs());
-  CurrTL = DASTL.getPointeeTypeLoc().getUnqualifiedLoc();
-}
-
 // An AtomicTypeLoc might be produced by an atomic qualifier in this
 // declarator chunk.
 if (AtomicTypeLoc ATL = CurrTL.getAs()) {
@@ -5615,6 +5609,12 @@
   CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
 }
 
+while (DependentAddressSpaceTypeLoc TL =
+   CurrTL.getAs()) {
+  fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs());
+  CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc();
+}
+
 // FIXME: Ordering here?
 while (AdjustedTypeLoc TL = CurrTL.getAs())
   CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
@@ -5767,7 +5767,10 @@
 /// specified type.  The attribute contains 1 argument, the id of the address
 /// space for the type.
 static void HandleAddressSpaceTypeAttribute(QualType &Type,
-const ParsedAttr &Attr, Sema &S) {
+const ParsedAttr &Attr,
+TypeProcessingState &State) {
+  Sema &S = State.getSema();
+
   // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be
   // qualified by an address-space qualifier."
   if (Type->isFunctionType()) {
@@ -5809,10 +5812,15 @@
 // the type.
 QualType T = S.BuildAddressSpaceAttr(Type, ASArgExpr, Attr.getLoc());
 
-if (!T.isNull())
-  Type = T;
-else
+if (!T.isNull()) {
+  ASTContext &Ctx = S.Context;
+  auto *ASAttr = ::new (Ctx) AddressSpaceAttr(
+  Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(),
+  static_cast(T.getQualifiers().getAddressSpace()));
+  Type = State.getAttributedType(ASAttr, T, T);
+} else {
   Attr.setInvalid();
+}
   } else {
 // The keyword-based type attributes imply which address space to use.
 switch (Attr.getKind()) {
@@ -7282,7 +7290,7 @@
 case ParsedAttr::AT_OpenCLConstantAddressSpace:
 case ParsedAttr::AT_OpenCLGenericAddressSpace:
 case ParsedAttr::AT_AddressSpace:
-  HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
+  HandleAddressSpaceTypeAttribute(type, attr, state);
   attr.setUsedAsTypeAttr();
   break;
 OBJC_POINTER_TYPE_ATTRS_CASELIST:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D51329: [Attribute/Diagnostics] Print macro instead of whole attribute for address_space

2018-08-27 Thread Leonard Chan via Phabricator via cfe-commits
leonardchan created this revision.
leonardchan added reviewers: rsmith, rjmccall, ebevhan, mcgrathr, phosek.
leonardchan added a project: clang.

If an `address_space` attribute is defined in a macro, print the macro instead 
when diagnosing a warning or error for incompatible pointers with different 
address_spaces.

Originally started from 
http://lists.llvm.org/pipermail/cfe-dev/2018-August/058702.html where the 
original proposal was a new pragma, but instead just changing the way 
`address_space` gets printed in a diagnostic.


Repository:
  rC Clang

https://reviews.llvm.org/D51329

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/Type.h
  include/clang/Lex/Preprocessor.h
  lib/AST/ASTContext.cpp
  lib/AST/TypePrinter.cpp
  lib/Lex/PPDirectives.cpp
  lib/Sema/SemaType.cpp
  test/Sema/address_space_print_macro.c
  test/Sema/address_spaces.c

Index: test/Sema/address_spaces.c
===
--- test/Sema/address_spaces.c
+++ test/Sema/address_spaces.c
@@ -71,5 +71,5 @@
 
 // Clang extension doesn't forbid operations on pointers to different address spaces.
 char* cmp(_AS1 char *x,  _AS2 char *y) {
-  return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type  ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *') which are pointers to non-overlapping address spaces}}
+  return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type  ('_AS1 char *' and '_AS2 char *') which are pointers to non-overlapping address spaces}}
 }
Index: test/Sema/address_space_print_macro.c
===
--- /dev/null
+++ test/Sema/address_space_print_macro.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+
+#define _AS1 __attribute__((address_space(1)))
+#define _AS2 __attribute__((address_space(2)))
+
+char *cmp(_AS1 char *x, _AS2 char *y) {
+  return x < y ? x : y; // expected-error{{conditional operator with the second and third operands of type  ('_AS1 char *' and '_AS2 char *') which are pointers to non-overlapping address spaces}}
+}
+
+__attribute__((address_space(1))) char test_array[10];
+void test3(void) {
+  extern void test3_helper(char *p); // expected-note{{passing argument to parameter 'p' here}}
+  test3_helper(test_array);  // expected-error{{passing '__attribute__((address_space(1))) char *' to parameter of type 'char *' changes address space of pointer}}
+}
+
+char _AS2 *test4_array;
+void test4(void) {
+  extern void test3_helper(char *p); // expected-note{{passing argument to parameter 'p' here}}
+  test3_helper(test4_array); // expected-error{{passing '_AS2 char *' to parameter of type 'char *' changes address space of pointer}}
+}
+
+void func() {
+  char _AS1 *x;
+  char *y = x; // expected-error{{initializing 'char *' with an expression of type '_AS1 char *' changes address space of pointer}}
+}
Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -243,9 +243,10 @@
 /// Get an attributed type for the given attribute, and remember the Attr
 /// object so that we can attach it to the AttributedTypeLoc.
 QualType getAttributedType(Attr *A, QualType ModifiedType,
-   QualType EquivType) {
-  QualType T =
-  sema.Context.getAttributedType(A->getKind(), ModifiedType, EquivType);
+   QualType EquivType,
+   IdentifierInfo *AddressSpaceMacroII = nullptr) {
+  QualType T = sema.Context.getAttributedType(
+  A->getKind(), ModifiedType, EquivType, AddressSpaceMacroII);
   AttrsForTypes.push_back({cast(T.getTypePtr()), A});
   AttrsForTypesSorted = false;
   return T;
@@ -5813,11 +5814,17 @@
 QualType T = S.BuildAddressSpaceAttr(Type, ASArgExpr, Attr.getLoc());
 
 if (!T.isNull()) {
+  IdentifierInfo *AddressSpaceMacroII = nullptr;
+  auto FoundMacro = S.PP.AddressSpaceMacros.find(
+  S.SourceMgr.getSpellingLoc(Attr.getLoc()));
+  if (FoundMacro != S.PP.AddressSpaceMacros.end())
+AddressSpaceMacroII = FoundMacro->second;
+
   ASTContext &Ctx = S.Context;
   auto *ASAttr = ::new (Ctx) AddressSpaceAttr(
   Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(),
   static_cast(T.getQualifiers().getAddressSpace()));
-  Type = State.getAttributedType(ASAttr, T, T);
+  Type = State.getAttributedType(ASAttr, T, T, AddressSpaceMacroII);
 } else {
   Attr.setInvalid();
 }
Index: lib/Lex/PPDirectives.cpp
===
--- lib/Lex/PPDirectives.cpp
+++ lib/Lex/PPDirectives.cpp
@@ -2577,6 +2577,22 @@
   MI->setDefinitionEndLoc(LastTok.getLocation());
   return MI;
 }
+
+static bool DefinesAddre

  1   2   3   4   5   6   7   8   9   >