diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index acf78efad6602d265aa4a667d2ddae5db9c79f72..417f7931df47a6b6acd03b22db56a88065250fa8 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -1424,8 +1424,11 @@ static bool IsWeakLValue(const LValue &Value) { static bool isZeroSized(const LValue &Value) { const ValueDecl *Decl = GetLValueBaseDecl(Value); - return Decl && isa(Decl) && - Decl->getASTContext().getTypeSize(Decl->getType()) == 0; + if (Decl && isa(Decl)) { + QualType Ty = Decl->getType(); + return Ty->isIncompleteType() || Decl->getASTContext().getTypeSize(Ty) == 0; + } + return false; } static bool EvalPointerValueAsBool(const APValue &Value, bool &Result) { @@ -6987,7 +6990,8 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { return Error(E); // We can't tell whether an object is at the same address as another // zero sized object. - if (isZeroSized(LHSValue) || isZeroSized(RHSValue)) + if ((RHSValue.Base && isZeroSized(LHSValue)) || + (LHSValue.Base && isZeroSized(RHSValue))) return Error(E); // Pointers with different bases cannot represent the same object. // (Note that clang defaults to -fmerge-all-constants, which can diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 9a650087f9a8b881e9090bae506635f55cf86c4a..5fb6f2c5f81c5bed2b3ee12960faea3a43f152b9 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1960,4 +1960,12 @@ namespace PR21786 { extern void (*start[])(); extern void (*end[])(); static_assert(&start != &end, ""); // expected-error {{constant expression}} + + struct Foo; + struct Bar { + static const Foo x; + static const Foo y; + }; + static_assert(&Bar::x != nullptr, ""); + static_assert(&Bar::x != &Bar::y, ""); // expected-error {{constant expression}} }