From: Eli Friedman Date: Fri, 28 Jun 2013 21:07:41 +0000 (+0000) Subject: Fix error recovery with in-class initializer. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5fb478be9b91f15624e855e7bd6ac2101021ac48;p=clang Fix error recovery with in-class initializer. Previously, for a field with an invalid in-class initializer, we would create a CXXDefaultInitExpr referring to a null Expr*. This is not a good idea. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185216 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 4a008a0ed3..77c3339507 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -919,6 +919,9 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef, FieldDecl *Field, llvm::SmallSet &Inits, bool &Diagnosed) { + if (Field->isInvalidDecl()) + return; + if (Field->isUnnamedBitfield()) return; @@ -3236,6 +3239,8 @@ static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) { static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, FieldDecl *Field, IndirectFieldDecl *Indirect = 0) { + if (Field->isInvalidDecl()) + return false; // Overwhelmingly common case: we have a direct initializer for this field. if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(Field)) @@ -3274,7 +3279,7 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, // Don't try to build an implicit initializer if there were semantic // errors in any of the initializers (and therefore we might be // missing some that the user actually wrote). - if (Info.AnyErrorsInInits || Field->isInvalidDecl()) + if (Info.AnyErrorsInInits) return false; CXXCtorInitializer *Init = 0; diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index ca029d9d12..dc8b6346fe 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -1694,3 +1694,18 @@ namespace VirtualFromBase { constexpr X *q = const_cast>*>(&xxs2); static_assert(q->f() == sizeof(S2), ""); } + +namespace ConstexprConstructorRecovery { + class X { + public: + enum E : short { + headers = 0x1, + middlefile = 0x2, + choices = 0x4 + }; + constexpr X() noexcept {}; + protected: + E val{0}; // expected-error {{cannot initialize a member subobject of type 'ConstexprConstructorRecovery::X::E' with an rvalue of type 'int'}} + }; + constexpr X x{}; +}