Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -1949,6 +1949,9 @@ "constexpr%select{; did you intend to make it %select{const|static}0?|}1">; def err_constexpr_tag : Error< "%select{class|struct|interface|union|enum}0 cannot be marked constexpr">; +def err_constexpr_ctor : Error<"constructor cannot be marked constexpr">; +def note_due_to_dllimported_class : Note< + "due to %0 being dllimported">; def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">; def err_constexpr_no_declarators : Error< "constexpr can only be used in variable and function declarations">; Index: lib/AST/DeclCXX.cpp =================================================================== --- lib/AST/DeclCXX.cpp +++ lib/AST/DeclCXX.cpp @@ -463,6 +463,12 @@ } } + // We cannot have a constexpr default constructor if the class is polymorphic + // because it is impossible to synthesize a reference to the imported vtable + // without generating code. + if (data().Polymorphic && hasAttr()) + data().DefaultedDefaultConstructorIsConstexpr = false; + // Notify the listener if an implicit member was added after the definition // was completed. if (!isBeingDefined() && D->isImplicit()) Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -808,15 +808,25 @@ // constraints: // - the class shall not have any virtual base classes; const CXXRecordDecl *RD = MD->getParent(); + bool IsCtor = isa(NewFD); if (RD->getNumVBases()) { Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base) - << isa(NewFD) + << IsCtor << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases(); for (const auto &I : RD->vbases()) Diag(I.getLocStart(), diag::note_constexpr_virtual_base_here) << I.getSourceRange(); return false; } + // A constructor for a polymorphic class cannot be constexpr if the class + // has been marked dllimport. This is because dllimport data cannot be + // resolved in a constant: code must be executed to dereference the __imp + // symbol. + if (IsCtor && RD->isPolymorphic() && RD->hasAttr()) { + Diag(NewFD->getLocation(), diag::err_constexpr_ctor); + Diag(RD->getLocStart(), diag::note_due_to_dllimported_class) << RD; + return false; + } } if (!isa(NewFD)) { Index: test/CodeGenCXX/dllimport.cpp =================================================================== --- test/CodeGenCXX/dllimport.cpp +++ test/CodeGenCXX/dllimport.cpp @@ -618,10 +618,10 @@ // GO1-DAG: @_ZTV1W = available_externally dllimport unnamed_addr constant [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] struct __declspec(dllimport) KeyFuncClass { - constexpr KeyFuncClass() {} + KeyFuncClass() {} virtual void foo(); }; -extern constexpr KeyFuncClass keyFuncClassVar = {}; +extern KeyFuncClass keyFuncClassVar = {}; // G32-DAG: @_ZTV12KeyFuncClass = external dllimport unnamed_addr constant [3 x i8*] struct __declspec(dllimport) X : public virtual W {}; Index: test/SemaCXX/dllimport.cpp =================================================================== --- test/SemaCXX/dllimport.cpp +++ test/SemaCXX/dllimport.cpp @@ -1259,6 +1259,15 @@ template struct ExpliciallySpecializedClassTemplate {}; template <> struct __declspec(dllimport) ExpliciallySpecializedClassTemplate { void f() {} }; +struct __declspec(dllimport) PR26506_test1 { + virtual ~PR26506_test1() {} + constexpr PR26506_test1() = default; // expected-error{{defaulted definition of default constructor is not constexpr}} +}; + +struct __declspec(dllimport) PR26506_test2 { // expected-note{{due to 'PR26506_test2' being dllimported}} + virtual ~PR26506_test2() {} + constexpr PR26506_test2() {} // expected-error{{constructor cannot be marked constexpr}} +}; //===----------------------------------------------------------------------===// // Classes with template base classes