From: David Majnemer Date: Thu, 11 Dec 2014 19:36:24 +0000 (+0000) Subject: AST: Incomplete types might be zero sized X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=70cbabae2254037475bd93211f18acda558a9f9e;p=clang AST: Incomplete types might be zero sized Comparing the address of an object with an incomplete type might return true with a 'distinct' object if the former has a size of zero. However, such an object should compare unequal with null. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@224040 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index acf78efad6..417f7931df 100644 --- a/lib/AST/ExprConstant.cpp +++ b/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/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 9a650087f9..5fb6f2c5f8 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/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}} }