r322984 - Allow BlockDecl in CXXRecord scope to have no access specifier.

Richard Trieu via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 19 15:24:03 PST 2018


Hans,

I recommend merging this revision into the release.  It fixes an assertion
error when mixing modules and blocks.

Richard


On Fri, Jan 19, 2018 at 12:46 PM, Richard Trieu via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> Author: rtrieu
> Date: Fri Jan 19 12:46:19 2018
> New Revision: 322984
>
> URL: http://llvm.org/viewvc/llvm-project?rev=322984&view=rev
> Log:
> Allow BlockDecl in CXXRecord scope to have no access specifier.
>
> Using a BlockDecl in a default member initializer causes it to be attached
> to
> CXXMethodDecl without its access specifier being set.  This prevents a
> crash
> where getAccess is called on this BlockDecl, since that method expects any
> Decl in CXXRecord scope to have an access specifier.
>
> Added:
>     cfe/trunk/test/Modules/odr_hash-blocks.cpp
> Modified:
>     cfe/trunk/lib/AST/DeclBase.cpp
>
> Modified: cfe/trunk/lib/AST/DeclBase.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBa
> se.cpp?rev=322984&r1=322983&r2=322984&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/DeclBase.cpp (original)
> +++ cfe/trunk/lib/AST/DeclBase.cpp Fri Jan 19 12:46:19 2018
> @@ -891,12 +891,14 @@ bool Decl::AccessDeclContextSanity() con
>    // 4. the context is not a record
>    // 5. it's invalid
>    // 6. it's a C++0x static_assert.
> +  // 7. it's a block literal declaration
>    if (isa<TranslationUnitDecl>(this) ||
>        isa<TemplateTypeParmDecl>(this) ||
>        isa<NonTypeTemplateParmDecl>(this) ||
>        !isa<CXXRecordDecl>(getDeclContext()) ||
>        isInvalidDecl() ||
>        isa<StaticAssertDecl>(this) ||
> +      isa<BlockDecl>(this) ||
>        // FIXME: a ParmVarDecl can have ClassTemplateSpecialization
>        // as DeclContext (?).
>        isa<ParmVarDecl>(this) ||
>
> Added: cfe/trunk/test/Modules/odr_hash-blocks.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/
> odr_hash-blocks.cpp?rev=322984&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Modules/odr_hash-blocks.cpp (added)
> +++ cfe/trunk/test/Modules/odr_hash-blocks.cpp Fri Jan 19 12:46:19 2018
> @@ -0,0 +1,119 @@
> +// Clear and create directories
> +// RUN: rm -rf %t
> +// RUN: mkdir %t
> +// RUN: mkdir %t/cache
> +// RUN: mkdir %t/Inputs
> +
> +// Build first header file
> +// RUN: echo "#define FIRST" >> %t/Inputs/first.h
> +// RUN: cat %s               >> %t/Inputs/first.h
> +
> +// Build second header file
> +// RUN: echo "#define SECOND" >> %t/Inputs/second.h
> +// RUN: cat %s                >> %t/Inputs/second.h
> +
> +// Test that each header can compile
> +// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++11 -fblocks
> %t/Inputs/first.h
> +// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++11 -fblocks
> %t/Inputs/second.h
> +
> +// Build module map file
> +// RUN: echo "module FirstModule {"     >> %t/Inputs/module.map
> +// RUN: echo "    header \"first.h\""   >> %t/Inputs/module.map
> +// RUN: echo "}"                        >> %t/Inputs/module.map
> +// RUN: echo "module SecondModule {"    >> %t/Inputs/module.map
> +// RUN: echo "    header \"second.h\""  >> %t/Inputs/module.map
> +// RUN: echo "}"                        >> %t/Inputs/module.map
> +
> +// Run test
> +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps \
> +// RUN:            -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs \
> +// RUN:            -verify %s -std=c++11 -fblocks
> +
> +#if !defined(FIRST) && !defined(SECOND)
> +#include "first.h"
> +#include "second.h"
> +#endif
> +
> +// Used for testing
> +#if defined(FIRST)
> +#define ACCESS public:
> +#elif defined(SECOND)
> +#define ACCESS private:
> +#endif
> +
> +// TODO: S1, S2, and S3 should generate errors.
> +namespace Blocks {
> +#if defined(FIRST)
> +struct S1 {
> +  void (^block)(int x) = ^(int x) { };
> +};
> +#elif defined(SECOND)
> +struct S1 {
> +  void (^block)(int x) = ^(int y) { };
> +};
> +#else
> +S1 s1;
> +#endif
> +
> +#if defined(FIRST)
> +struct S2 {
> +  int (^block)(int x) = ^(int x) { return x + 1; };
> +};
> +#elif defined(SECOND)
> +struct S2 {
> +  int (^block)(int x) = ^(int x) { return x; };
> +};
> +#else
> +S2 s2;
> +#endif
> +
> +#if defined(FIRST)
> +struct S3 {
> +  void run(int (^block)(int x));
> +};
> +#elif defined(SECOND)
> +struct S3 {
> +  void run(int (^block)(int x, int y));
> +};
> +#else
> +S3 s3;
> +#endif
> +
> +#define DECLS                                       \
> +  int (^block)(int x) = ^(int x) { return x + x; }; \
> +  void run(int (^block)(int x, int y));
> +
> +#if defined(FIRST) || defined(SECOND)
> +struct Valid1 {
> +  DECLS
> +};
> +#else
> +Valid1 v1;
> +#endif
> +
> +#if defined(FIRST) || defined(SECOND)
> +struct Invalid1 {
> +  DECLS
> +  ACCESS
> +};
> +#else
> +Invalid1 i1;
> +// expected-error at second.h:* {{'Blocks::Invalid1' has different
> definitions in different modules; first difference is definition in module
> 'SecondModule' found private access specifier}}
> +// expected-note at first.h:* {{but in 'FirstModule' found public access
> specifier}}
> +#endif
> +
> +#undef DECLS
> +}
> +
> +// Keep macros contained to one file.
> +#ifdef FIRST
> +#undef FIRST
> +#endif
> +
> +#ifdef SECOND
> +#undef SECOND
> +#endif
> +
> +#ifdef ACCESS
> +#undef ACCESS
> +#endif
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180119/1ec80c64/attachment-0001.html>


More information about the cfe-commits mailing list