This is an archive of the discontinued LLVM Phabricator instance.

[ObjC++] Don't enter a C++ declarator context when the current context is an Objective-C declaration
ClosedPublic

Authored by arphaman on Nov 21 2016, 10:18 AM.

Details

Summary

This patch ensures that Sema won't enter a C++ declarator context when the current context is an Objective-C declaration. This prevents an assertion failure in EnterDeclaratorContext that's used to ensure that current context will be restored correctly after exiting the declarator context. I think that this approach is reasonable as AFAIK we don't need to use the C++ declarator contexts directly in Objective-C declarations, since they're mostly used to define out of line variables declared in classes or namespaces which shouldn't be done inside an Objective-C declaration.

Diff Detail

Repository
rL LLVM

Event Timeline

arphaman updated this revision to Diff 78737.Nov 21 2016, 10:18 AM
arphaman retitled this revision from to [ObjC++] Don't enter a C++ declarator context when the current context is an Objective-C declaration.
arphaman updated this object.
arphaman added reviewers: manmanren, ahatanak.
arphaman set the repository for this revision to rL LLVM.
arphaman added a subscriber: cfe-commits.
ahatanak edited edge metadata.Nov 28 2016, 3:49 PM

I wonder whether it is possible to avoid calling DeclScopeObj.EnterDeclaratorScope at ParseDecl.cpp:5317 instead of fixing Sema::ActOnCXXEnterDeclaratorScope?

I believe it's calling EnterDeclaratorScope to enable name lookup when a namespace-member variable is defined outside the namespace. Since that's not the case here, it seems to me that it shouldn't called in the first place.

http://en.cppreference.com/w/cpp/language/unqualified_lookup

I wonder whether it is possible to avoid calling DeclScopeObj.EnterDeclaratorScope at ParseDecl.cpp:5317 instead of fixing Sema::ActOnCXXEnterDeclaratorScope?

I believe it's calling EnterDeclaratorScope to enable name lookup when a namespace-member variable is defined outside the namespace. Since that's not the case here, it seems to me that it shouldn't called in the first place.

http://en.cppreference.com/w/cpp/language/unqualified_lookup

Do you mean at ParseDecl:5266 (I get this line in the crash backtrace with ToT)?

AFAIK it's also used for static class member lookups for variables defined outside of a class. The OuterType is a C++ record so that's why it should be valid to call EnterDeclaratorScope there. I tested to verify this and I reach that call on line 5266 with the following example 3 times:

namespace Foo {
 extern int x;
}

int Foo::x = 2; // EnterDeclaratorScope is called here

class Bar {
public:
   void foo();
   static int m;
};

int Bar::m = 2; // here

class FooBar {
  friend void Bar::foo(); // and here
};

So it doesn't seem reasonable to required this only for namespaces.

I suppose it might be better to avoid calling EnterDeclaratorScope anyway by moving the current context ObjC isa checks to ShouldEnterDeclaratorScope.

Yes, I meant ParseDecl:5266. Reading the comment in ShouldEnterDeclaratorScope, it seemed to me that it shouldn't return true in this context (when parsing an objective-c).

Also, the following code (which is not valid) crashes with ToT trunk,

@property (nonatomic) int OuterType::InnerType

but compiles without any errors with your patch applied. Do you know why clang doesn't error out?

Yes, I meant ParseDecl:5266. Reading the comment in ShouldEnterDeclaratorScope, it seemed to me that it shouldn't return true in this context (when parsing an objective-c).

Also, the following code (which is not valid) crashes with ToT trunk,

@property (nonatomic) int OuterType::InnerType

but compiles without any errors with your patch applied. Do you know why clang doesn't error out?

Hmm, that's interesting, I have to investigate this. It looks like clang is creating a property named InnerType which is obviously invalid.

Yes, I meant ParseDecl:5266. Reading the comment in ShouldEnterDeclaratorScope, it seemed to me that it shouldn't return true in this context (when parsing an objective-c).

Yes, I agree that it's better to move the check to ShouldEnterDeclaratorScope, I will update the patch.

Also, the following code (which is not valid) crashes with ToT trunk,

@property (nonatomic) int OuterType::InnerType

but compiles without any errors with your patch applied. Do you know why clang doesn't error out?

arphaman updated this revision to Diff 79722.Nov 30 2016, 4:04 AM
arphaman edited edge metadata.

The updated patch performs the check in ShouldEnterDeclaratorScope.

Also, the following code (which is not valid) crashes with ToT trunk,

@property (nonatomic) int OuterType::InnerType

but compiles without any errors with your patch applied. Do you know why clang doesn't error out?

This worked because clang continued parsing InnerType as the name of the property. The updated patch fixes this by ensuring that we don't interpret this token as a property name, so now this example will have a compilation error.

ahatanak accepted this revision.Dec 1 2016, 12:51 PM
ahatanak edited edge metadata.

I think this is fine.

I guess we can print a more helpful error message than "error: property requires fields to be named", but we can probably do it later.

This revision is now accepted and ready to land.Dec 1 2016, 12:51 PM
This revision was automatically updated to reflect the committed changes.