From 27db35878dccd6dd5e62130f644bf01939f56716 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 11 Dec 2014 19:36:24 +0000 Subject: [PATCH] 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. llvm-svn: 224040 --- clang/lib/AST/ExprConstant.cpp | 10 +++++++--- clang/test/SemaCXX/constant-expression-cxx11.cpp | 8 ++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index acf78ef..417f793 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 9a65008..5fb6f2c 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}} } -- 2.7.4