Skip to content

Conversation

@hughbe
Copy link
Contributor

@hughbe hughbe commented Nov 28, 2016

Relies on apple/swift-llvm#33 but can be merged before

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eeckstein PTAL, this changes your recently committed code - I think this was a case of Clang allowing something that perhaps isn't spec-ed C++?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this just looks like a mistake.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it was

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes an MSVC error: cannot instantiate abstract class FileUnit. I'm not sure how correct this is (@jrose-apple you seem to know a lot of these sorts of things)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely not correct, except coincidentally. Also confused; this operator occurs within the definition of FileUnit, so I would expect it to be able to calculate the alignment.

…well, okay, maybe not, that might require two passes. *goes to check C++ standard*

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, this actually does look correct—"When alignof is applied to a reference type, the result shall be the alignment of the referenced type." (C++11 [expr.alignof]p3)—but if MSVC is accepting one and not the other I'm a little concerned that it's doing the wrong thing. Can you test that it accepts this code?

struct Foo {
  bool b;
  static_assert(alignof(Foo&) == alignof(bool), "aligning reference rather than Foo");
};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specific citation allowing this (which says nothing to whether MSVC implements it): "Within the class member-specification, the class is regarded as complete within function bodies, default arguments, and brace-or-equal-initializers for non-static data members (including such things in nested classes)." (C++11 [class.mem]p2)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following modification of your example works:

struct Foo {
  bool b;
};

 static_assert(alignof(Foo&) == alignof(bool), "aligning reference rather than Foo");

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, something like this:

class FileUnit {
public:
  // Only allow allocation of FileUnits using the allocator in ASTContext
  // or by doing a placement new.
  void *operator new(size_t Bytes, ASTContext &C,
                     unsigned Alignment = alignOfFileUnit());
};

static inline unsigned alignOfFileUnit() {
	return alignof(FileUnit);
}

doesn't work due to same error:

1>C:\Users\Lukey\Documents\GitHub\my-swift\swift\include\swift/AST/Module.h(757): error C2259: 'swift::FileUnit': cannot instantiate abstract class (compiling source file C:\Users\Lukey\Documents\GitHub\my-swift\swift\lib\AST\ASTPrinter.cpp)
1> C:\Users\Lukey\Documents\GitHub\my-swift\swift\include\swift/AST/Module.h(757): note: due to following members: (compiling source file C:\Users\Lukey\Documents\GitHub\my-swift\swift\lib\AST\ASTPrinter.cpp)
1> C:\Users\Lukey\Documents\GitHub\my-swift\swift\include\swift/AST/Module.h(757): note: 'void swift::FileUnit::lookupValue(swift::ModuleDecl::AccessPathTy,swift::DeclName,swift::NLKind,llvm::SmallVectorImpl<swift::ValueDecl *> &) const': is abstract (compiling source file C:\Users\Lukey\Documents\GitHub\my-swift\swift\lib\AST\ASTPrinter.cpp)
1> C:\Users\Lukey\Documents\GitHub\my-swift\swift\include\swift/AST/Module.h(556): note: see declaration of 'swift::FileUnit::lookupValue' (compiling source file C:\Users\Lukey\Documents\GitHub\my-swift\swift\lib\AST\ASTPrinter.cpp)
1> C:\Users\Lukey\Documents\GitHub\my-swift\swift\include\swift/AST/Module.h(757): note: 'void swift::FileUnit::lookupObjCMethods(swift::ObjCSelector,llvm::SmallVectorImpl<swift::AbstractFunctionDecl *> &) const': is abstract (compiling source file C:\Users\Lukey\Documents\GitHub\my-swift\swift\lib\AST\ASTPrinter.cpp)
1> C:\Users\Lukey\Documents\GitHub\my-swift\swift\include\swift/AST/Module.h(588): note: see declaration of 'swift::FileUnit::lookupObjCMethods' (compiling source file C:\Users\Lukey\Documents\GitHub\my-swift\swift\lib\AST\ASTPrinter.cpp)
1> C:\Users\Lukey\Documents\GitHub\my-swift\swift\include\swift/AST/Module.h(757): note: 'swift::Identifier swift::FileUnit::getDiscriminatorForPrivateValue(const swift::ValueDecl *) const': is abstract (compiling source file C:\Users\Lukey\Documents\GitHub\my-swift\swift\lib\AST\ASTPrinter.cpp)
1> C:\Users\Lukey\Documents\GitHub\my-swift\swift\include\swift/AST/Module.h(631): note: see declaration of 'swift::FileUnit::getDiscriminatorForPrivateValue' (compiling source file C:\Users\Lukey\Documents\GitHub\my-swift\swift\lib\AST\ASTPrinter.cpp)

Copy link
Contributor

@jrose-apple jrose-apple Dec 12, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that's a much more enlightening error. I forgot about the virtual function.

Does the reference do the right thing now?

class Test {
  alignas(16) double x;
public:
  virtual void foo() = 0;
};

static_assert(alignof(Test&) == 16, "");

(Of course, maybe MSVC doesn't support overalignment, in which case the test won't work again.)

Copy link
Contributor Author

@hughbe hughbe Dec 12, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This console application compiles and runs just fine

// ConsoleApplication2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string>
#include <io.h>

class Test {
  alignas(16) double x;
public:
  virtual void foo() = 0;
};

static_assert(alignof(Test&) == 16, "");

int main()
{
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, then in that case we can use alignof(FileUnit&) in alignOfFileUnit and we should get the correct answer.

(I think this is actually important because DeclContexts are deliberately overaligned, and we rely on that to cram things in the low bits.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clang still has unknown pragma warnings on, so this should be guarded by a check for MSVC.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah I assumed if this worked with clang-cl it would work with Clang, but I was wrong - fixed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does MSVC consider a reference that Clang doesn't?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the following error

error C2280: 'void *swift::AST::ModuleDecl::__delDtor(unsigned int)': attempting to reference a deleted function

The problem seems to be that MSVC generates this __delDtor intrinsic that I don't seem to have control over.

Copy link
Contributor Author

@hughbe hughbe Dec 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take a look at this link: https://msdn.microsoft.com/en-us/library/mt723604.aspx
There seems to be some mention of this error, but I'm not sure how applicable this is, so I'd appreciate your expertise

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, maybe you would then have to delete operator delete in all the subclasses too.

It's possible marking it virtual would work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, maybe you would then have to delete operator delete in all the subclasses too.

This doesn't work - it just changes the error message from

void swift::Decl::operator delete(void *)': attempting to reference a deleted function

to

void swift::ModuleDecl::operator delete(void *)': attempting to reference a deleted function

Making it virtual causes the error

'delete' cannot be a virtual function

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All right, oh well. We can do the workaround.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like an MSVC bug. I presume the deleting destructor is part of its ABI, but that entry point seems like it ought to be transitively delete-d if operator delete is deleted.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can believe it's an MSVC bug, but I don't mind us working around it for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems really brittle. I still don't like it, but I don't have an alternative to play with right now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hate this too, but seems to be the best I can figure out

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're going to do this, just write the constant unconditionally, and static_assert that it has the correct value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't seem to reproduce this - I think it is a Visual Studio bug. I've removed the workaround

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this just looks like a mistake.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can just include <cassert> unconditionally. What's intrin.h for?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see, it's the popcnt check below. I think it's fine to leave that out, since the static_assert will be checked in Clang anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry - I'm a tad confused. Do you suggest not changing this file, or simply to move <cassert> out of the if

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, both. :-) Please move <cassert> out of the #if, but don't bother asserting the popcount under MSVC (just #if it out).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, thanks

@hughbe
Copy link
Contributor Author

hughbe commented Dec 12, 2016

I've rebased and addressed your comments about the alignment issues

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few last comments.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More unguarded pragmas. Also, I find it hard to believe that we'd get a warning on this code and not the previous line, so maybe this is no longer necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do get the following warning:

C:\Users\Lukey\Documents\GitHub\my-swift\swift\lib\AST\ASTContext.cpp(282): warning C4189: 'conformance': local variable is initialized but not referenced

very weird...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:-(

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(To be clear, no action requested. This just seems like a horrible oversight on MSVC's part.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I have a much better fix that suddenly came to me when you commented. Basically, the problem was that the code referring to this << operator is in an anonymous namespace. Moving << into that anonymous namespace fixes this. Unfortunately, MSVC wasn't very helpful as it reported the error as an ambiguous overload error for unsigned char

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the change here? These do different things. cc @eeckstein

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whoops - merge conflict

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tabs snuck in here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - this should be fixed now

@hughbe
Copy link
Contributor Author

hughbe commented Dec 15, 2016

I've made a connect bug for the numTrailingObjects problem: https://connect.microsoft.com/VisualStudio/feedback/details/3116517

If anyone's curious, they can try coming up with a better workaround by compiling MSVC code online here: http://rextester.com/XIJ43194

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be a bug in MSVC: I've been trying hard to reproduce this came, but can't.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this looks to be an MSVC bug, but I can't reproduce it :(

@hughbe
Copy link
Contributor Author

hughbe commented Jan 9, 2017

@slavapestov PTAL. I think the only thing holding back this one getting merged is the gross hack for https://connect.microsoft.com/VisualStudio/feedback/details/3116517. I'd like to figure out a work around that doesn't make us diverge from upstream LLVM.

If anyone has some spare time, check out a simple reproduction here and help me find a nicer fix for MSVC's bug: http://rextester.com/XIJ43194. This one also lets you compile C++ online if you don't have a Windows PC

@slavapestov
Copy link
Contributor

@swift-ci Please smoke test

@slavapestov slavapestov self-assigned this Jan 9, 2017
@slavapestov slavapestov merged commit 55f979c into swiftlang:master Jan 9, 2017
@hughbe hughbe deleted the ast-msvc branch January 9, 2017 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants