[PATCH] D45713: [libclang] Fix the type of 'int (Foo);'

2018-04-16 Thread strager via Phabricator via cfe-commits
strager created this revision.
strager added a reviewer: cfe-commits.

libclang exposes the type of 'int (Foo);' (a global variable of type int
called Foo) as CXType_Unexposed. This is because Clang represents Foo's
type as ParenType{BuiltinType{Int}}, and libclang does not handle
ParenType.

Make libclang return CXType_Int as the type of 'int (Foo);' by
unwrapping ParenType transparently.


Repository:
  rC Clang

https://reviews.llvm.org/D45713

Files:
  test/Index/paren-type.c
  test/Index/print-type.c
  tools/libclang/CXType.cpp


Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -119,6 +119,10 @@
 if (auto *ATT = T->getAs()) {
   return MakeCXType(ATT->getModifiedType(), TU);
 }
+// Handle paren types as the original type
+if (auto *PTT = T->getAs()) {
+  return MakeCXType(PTT->getInnerType(), TU);
+}
 
 ASTContext &Ctx = cxtu::getASTUnit(TU)->getASTContext();
 if (Ctx.getLangOpts().ObjC1) {
Index: test/Index/print-type.c
===
--- test/Index/print-type.c
+++ test/Index/print-type.c
@@ -23,11 +23,11 @@
 // CHECK: TypeRef=FooType:1:13 [type=FooType] [typekind=Typedef] 
[canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
 // CHECK: ParmDecl=arr:3:40 (Definition) [type=int [5]] 
[typekind=ConstantArray] [isPOD=1]
 // CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1]
-// CHECK: ParmDecl=fn:3:55 (Definition) [type=void (*)(int)] 
[typekind=Pointer] [canonicaltype=void (*)(int)] [canonicaltypekind=Pointer] 
[isPOD=1] [pointeetype=void (int)] [pointeekind=Unexposed]
+// CHECK: ParmDecl=fn:3:55 (Definition) [type=void (*)(int)] 
[typekind=Pointer] [canonicaltype=void (*)(int)] [canonicaltypekind=Pointer] 
[isPOD=1] [pointeetype=void (int)] [pointeekind=FunctionProto]
 // CHECK: ParmDecl=:3:62 (Definition) [type=int] [typekind=Int] [isPOD=1]
 // CHECK: CompoundStmt= [type=] [typekind=Invalid] [isPOD=0]
 // CHECK: CallExpr=fn:3:55 [type=void] [typekind=Void] [args= [int] [Int]] 
[isPOD=0]
-// CHECK: DeclRefExpr=fn:3:55 [type=void (*)(int)] [typekind=Pointer] 
[canonicaltype=void (*)(int)] [canonicaltypekind=Pointer] [isPOD=1] 
[pointeetype=void (int)] [pointeekind=Unexposed]
+// CHECK: DeclRefExpr=fn:3:55 [type=void (*)(int)] [typekind=Pointer] 
[canonicaltype=void (*)(int)] [canonicaltypekind=Pointer] [isPOD=1] 
[pointeetype=void (int)] [pointeekind=FunctionProto]
 // CHECK: UnaryOperator= [type=int] [typekind=Int] [isPOD=1]
 // CHECK: DeclRefExpr=p:3:13 [type=int *] [typekind=Pointer] [isPOD=1] 
[pointeetype=int] [pointeekind=Int]
 // CHECK: DeclStmt= [type=] [typekind=Invalid] [isPOD=0]
Index: test/Index/paren-type.c
===
--- /dev/null
+++ test/Index/paren-type.c
@@ -0,0 +1,16 @@
+// RUN: c-index-test -test-print-type %s | FileCheck --check-prefix=CHECK-TYPE 
%s
+// RUN: c-index-test -test-print-type-declaration %s | FileCheck 
--check-prefix=CHECK-TYPEDECL %s
+
+// CHECK-TYPE: VarDecl=VariableWithParentheses:
+// CHECK-TYPE-SAME: [type=int] [typekind=Int]
+// CHECK-TYPE-NOT: canonicaltype
+// CHECK-TYPE-SAME: isPOD
+extern int (VariableWithParentheses);
+
+typedef int MyTypedef;
+// CHECK-TYPE: VarDecl=VariableWithParentheses2:
+// CHECK-TYPE-SAME: [type=MyTypedef] [typekind=Typedef]
+// CHECK-TYPE-SAME: [canonicaltype=int] [canonicaltypekind=Int]
+// CHECK-TYPEDECL: VarDecl=VariableWithParentheses2
+// CHECK-TYPEDECL-SAME: [typedeclaration=MyTypedef] [typekind=Typedef]
+extern MyTypedef (VariableWithParentheses2);


Index: tools/libclang/CXType.cpp
===
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -119,6 +119,10 @@
 if (auto *ATT = T->getAs()) {
   return MakeCXType(ATT->getModifiedType(), TU);
 }
+// Handle paren types as the original type
+if (auto *PTT = T->getAs()) {
+  return MakeCXType(PTT->getInnerType(), TU);
+}
 
 ASTContext &Ctx = cxtu::getASTUnit(TU)->getASTContext();
 if (Ctx.getLangOpts().ObjC1) {
Index: test/Index/print-type.c
===
--- test/Index/print-type.c
+++ test/Index/print-type.c
@@ -23,11 +23,11 @@
 // CHECK: TypeRef=FooType:1:13 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
 // CHECK: ParmDecl=arr:3:40 (Definition) [type=int [5]] [typekind=ConstantArray] [isPOD=1]
 // CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1]
-// CHECK: ParmDecl=fn:3:55 (Definition) [type=void (*)(int)] [typekind=Pointer] [canonicaltype=void (*)(int)] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=void (int)] [pointeekind=Unexposed]
+// CHECK: ParmDecl=fn:3:55 (Definition) [type=void (*)(int)] [typekind=Pointer] [canonicaltype=void (*)(int)] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=void (

[PATCH] D45779: [ARM] Remove redundant #if in test

2018-04-18 Thread strager via Phabricator via cfe-commits
strager created this revision.
strager added a reviewer: cfe-commits.
Herald added subscribers: chrib, kristof.beyls, javed.absar.

Both sides of this #if #include the same file. Drop the #if, leaving only the 
#include.

This commit should not change behaviour.


Repository:
  rC Clang

https://reviews.llvm.org/D45779

Files:
  test/CodeGen/arm-aapcs-vfp.c


Index: test/CodeGen/arm-aapcs-vfp.c
===
--- test/CodeGen/arm-aapcs-vfp.c
+++ test/CodeGen/arm-aapcs-vfp.c
@@ -17,11 +17,7 @@
 // RUN:   -ffreestanding \
 // RUN:   -emit-llvm -w -o - %s | FileCheck -check-prefix=CHECK64 %s
 
-#ifdef __arm64__
 #include 
-#else
-#include 
-#endif
 
 struct homogeneous_struct {
   float f[2];


Index: test/CodeGen/arm-aapcs-vfp.c
===
--- test/CodeGen/arm-aapcs-vfp.c
+++ test/CodeGen/arm-aapcs-vfp.c
@@ -17,11 +17,7 @@
 // RUN:   -ffreestanding \
 // RUN:   -emit-llvm -w -o - %s | FileCheck -check-prefix=CHECK64 %s
 
-#ifdef __arm64__
 #include 
-#else
-#include 
-#endif
 
 struct homogeneous_struct {
   float f[2];
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D45713: [libclang] Fix the type of 'int (Foo);'

2018-04-26 Thread strager via Phabricator via cfe-commits
strager added a comment.

Ping! I'd like a code review for this bug fix.


Repository:
  rC Clang

https://reviews.llvm.org/D45713



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


[PATCH] D47111: : Implement monotonic_buffer_resource.

2019-10-11 Thread strager via Phabricator via cfe-commits
strager added inline comments.



Comment at: include/experimental/memory_resource:427
+static _LIBCPP_CONSTEXPR const size_t __default_buffer_capacity = 1024;
+static _LIBCPP_CONSTEXPR const size_t __default_buffer_alignment = 16;
+

Nit: Why isn't `__default_buffer_alignment` set to `alignof(max_align_t)` 
(which I think is 16)? I think `alignof(max_align_t)` is a good, portable 
default.



Comment at: include/experimental/memory_resource:431-432
+__chunk_header *__next_;
+char *__start_;
+char *__cur_;
+size_t __align_;

Nit: Would it make sense to use `std::byte` instead of `char`?



Comment at: 
test/libcxx/experimental/memory/memory.resource.monotonic.buffer/monotonic.buffer.mem/allocate_in_geometric_progression.pass.cpp:32
+assert(globalMemCounter.checkOutstandingNewEq(0));
+}
+

Nit: This test is named allocate_in_geometric_progression. I don't see any 
multiplication or anything happening in this test case. Did you mean to call 
this test something else, like release_deletes_upstream_memory?



Comment at: 
test/std/experimental/memory/memory.resource.monotonic.buffer/monotonic.buffer.mem/allocate_deallocate.pass.cpp:28
+std::experimental::pmr::monotonic_buffer_resource 
mono1(std::experimental::pmr::new_delete_resource());
+std::experimental::pmr::memory_resource & r1 = mono1;
+

Nit: What is the purpose of the `r1` variable? Why not use `mono1` everywhere 
instead (and rename `mono1` to `r1` if you like `r1` better than `mono1` as a 
name)?



Comment at: 
test/std/experimental/memory/memory.resource.monotonic.buffer/monotonic.buffer.mem/allocate_exception_safety.pass.cpp:48-49
+void *res = r1.allocate(64, 16);
+assert(res == buffer);
+assert(globalMemCounter.checkNewCalledEq(0));
+

Nit: These assertions look unrelated to exception safety to me. (The test is 
named allocate_exception_safety.) I'd delete these assertions.



Comment at: 
test/std/experimental/memory/memory.resource.monotonic.buffer/monotonic.buffer.mem/allocate_exception_safety.pass.cpp:52-54
+assert(res != buffer);
+assert(globalMemCounter.checkNewCalledEq(1));
+assert(globalMemCounter.checkDeleteCalledEq(0));

(Same comment as on lines 48-49 above. I'd delete these assertions.)



Comment at: 
test/std/experimental/memory/memory.resource.monotonic.buffer/monotonic.buffer.mem/allocate_exception_safety.pass.cpp:67-68
+
+upstream.which = std::experimental::pmr::new_delete_resource();
+res = r1.allocate(last_new_size, 16);
+assert(res != buffer);

Question about the intended behavior of `monotonic_buffer_resource`:

If line 68 instead allocated 1 byte, and the byte could fit in the original 
heap allocation (line 51), should `monotonic_buffer_resource` return a byte 
from that original resource? In other words, should the following test pass?

```
repointable_resource upstream(std::experimental::pmr::new_delete_resource());
std::experimental::pmr::monotonic_buffer_resource mono1(&upstream);

globalMemCounter.reset();
mono1.allocate(1, 1);
const size_t first_new_size = globalMemCounter.last_new_size;
bool mono1_has_spare_capacity = first_new_size == 1;

upstream.which = std::experimental::pmr::null_memory_resource();
try {
mono1.allocate(first_new_size, 1); // Force allocation from upstream.
assert(false);
} catch (const std::bad_alloc&) {
// we expect this
}

globalMemCounter.reset();
mono1.allocate(1, 1);
if (mono1_has_spare_capacity) {
  assert(globalMemCounter.checkNewCalledEq(0));
} else {
  assert(globalMemCounter.checkNewCalledEq(1));
}
```

Similarly, if `monotonic_buffer_resource` was given a buffer, and that buffer 
still has spare capacity, should that capacity be reused? In other words, 
should the following test pass?

```
int first_allocation_size = 20;
int second_allocation_size = 30;

auto *upstream = std::experimental::pmr::null_memory_resource();
char buffer[64];
assert(sizeof buffer >= first_allocation_size + second_allocation_size);
std::experimental::pmr::monotonic_buffer_resource mono1(buffer, sizeof buffer, 
upstream);

globalMemCounter.reset();
void *first_allocation = mono1.allocate(first_allocation_size, 1);
assert(first_allocation == &buffer[0]);

try {
mono1.allocate(sizeof buffer, 1); // Force allocation from upstream.
assert(false);
} catch (const std::bad_alloc&) {
// we expect this
}

void *second_allocation = mono1.allocate(second_allocation_size, 1);
assert(second_allocation == &buffer[second_allocation_size]);
```

I think these scenarios would be useful to test, in addition to the scenario in 
your test here.


Repository:
  rCXX libc++

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

https://reviews.llvm.org/D47111




[PATCH] D47111: : Implement monotonic_buffer_resource.

2019-10-11 Thread strager via Phabricator via cfe-commits
strager added inline comments.



Comment at: include/experimental/memory_resource:433
+char *__cur_;
+size_t __align_;
+size_t __allocation_size() {

> Eric suggests replacing size_t __align_ with uint8_t __log2_align_. I'm 
> amenable to this idea, but I'd want to know what's the best way to compute 
> the log2 of a user-supplied number.

Perhaps `std::log2p1` could help: 
https://en.cppreference.com/w/cpp/numeric/log2p1


Repository:
  rCXX libc++

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

https://reviews.llvm.org/D47111



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


[PATCH] D40221: [clang-format] Parse blocks in braced lists

2017-11-18 Thread strager via Phabricator via cfe-commits
strager created this revision.
Herald added a subscriber: klimek.

clang-format completely ruins the formatting of block literal
expressions which appear inside inside braced initializer lists. For
example:

  int main() {
foo({
  ^() {
return nil;
  }
  });
  }

Teach clang-format to parse blocks inside braced lists:

  int main() {
foo({^() {

return nil;

}});
  }


https://reviews.llvm.org/D40221

Files:
  lib/Format/UnwrappedLineParser.cpp
  lib/Format/UnwrappedLineParser.h
  unittests/Format/FormatTest.cpp

Index: unittests/Format/FormatTest.cpp
===
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -11200,6 +11200,85 @@
   verifyFormat("BOOL (^aaa)(void) = ^BOOL {\n"
"};");
 
+  verifyFormat("foo({^{\n"
+   "  return nil;\n"
+   "}});\n");
+  verifyFormat("foo({^() {\n"
+   "  return nil;\n"
+   "}});\n");
+  verifyFormat("foo({^id {\n"
+   "  return nil;\n"
+   "}});\n");
+  verifyFormat("foo({^id() {\n"
+   "  return nil;\n"
+   "}});\n");
+
+  verifyFormat("foo({.cb = ^{\n"
+   "  return nil;\n"
+   "}});\n");
+  verifyFormat("foo({.cb = ^() {\n"
+   "  return nil;\n"
+   "}});\n");
+  verifyFormat("foo({.cb = ^id {\n"
+   "  return nil;\n"
+   "}});\n");
+  verifyFormat("foo({.cb = ^id() {\n"
+   "  return nil;\n"
+   "}});\n");
+
+  verifyFormat("foo(\n"
+   "^{\n"
+   "  return nil;\n"
+   "},\n"
+   "^() {\n"
+   "  return [NSArray new];\n"
+   "});\n");
+  verifyFormat("foo(\n"
+   "^id {\n"
+   "  return nil;\n"
+   "},\n"
+   "^id() {\n"
+   "  return [NSArray new];\n"
+   "});\n");
+
+  verifyFormat("callbacks cbs = {\n"
+   "^{\n"
+   "  return nil;\n"
+   "},\n"
+   "^id {\n"
+   "  return [NSArray new];\n"
+   "},\n"
+   "};");
+  verifyFormat("callbacks cbs = {\n"
+   "^() {\n"
+   "  return nil;\n"
+   "},\n"
+   "^id() {\n"
+   "  return [NSArray new];\n"
+   "},\n"
+   "};");
+
+  verifyFormat("callbacks cbs = {\n"
+   ".cb1 =\n"
+   "^{\n"
+   "  return nil;\n"
+   "},\n"
+   ".cb2 =\n"
+   "^id {\n"
+   "  return [NSArray new];\n"
+   "},\n"
+   "};");
+  verifyFormat("callbacks cbs = {\n"
+   ".cb1 =\n"
+   "^() {\n"
+   "  return nil;\n"
+   "},\n"
+   ".cb2 =\n"
+   "^id() {\n"
+   "  return nil;\n"
+   "},\n"
+   "};");
+
   FormatStyle FourIndent = getLLVMStyle();
   FourIndent.ObjCBlockIndentWidth = 4;
   verifyFormat("[operation setCompletionBlock:^{\n"
Index: lib/Format/UnwrappedLineParser.h
===
--- lib/Format/UnwrappedLineParser.h
+++ lib/Format/UnwrappedLineParser.h
@@ -121,6 +121,7 @@
   void parseObjCInterfaceOrImplementation();
   void parseObjCProtocol();
   void parseJavaScriptEs6ImportExport();
+  bool tryToParseBlock();
   bool tryToParseLambda();
   bool tryToParseLambdaIntroducer();
   void tryToParseJSFunction();
Index: lib/Format/UnwrappedLineParser.cpp
===
--- lib/Format/UnwrappedLineParser.cpp
+++ lib/Format/UnwrappedLineParser.cpp
@@ -1177,14 +1177,7 @@
 nextToken();
   break;
 case tok::caret:
-  nextToken();
-  if (FormatTok->Tok.isAnyIdentifier() ||
-  FormatTok->isSimpleTypeSpecifier())
-nextToken();
-  if (FormatTok->is(tok::l_paren))
-parseParens();
-  if (FormatTok->is(tok::l_brace))
-parseChildBlock();
+  tryToParseBlock();
   break;
 case tok::l_brace:
   if (!tryToParseBracedList()) {
@@ -1311,6 +1304,40 @@
   } while (!eof());
 }
 
+// Parses a block literal expression starting at the initial ^ token.
+//
+// Blocks literal expressions have several forms including the following:
+//
+// \code
+// ^{
+//   return 42;
+// }
+//
+// ^BOOL(int x) {
+//   return x > 0;
+// }
+// \endcode
+bool UnwrappedLineParser::tryToParseBlock() {
+  // Consume the leading ^.
+  assert(FormatTok->is(tok::caret));
+  nextToken();
+  if (!Style.isCpp()) {
+// Blocks are only supported in C++ and