[PATCH] D45713: [libclang] Fix the type of 'int (Foo);'
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
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);'
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.
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.
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
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