From: David Majnemer Date: Tue, 9 Dec 2014 23:32:34 +0000 (+0000) Subject: AST: Don't assume two zero sized objects live at different addresses X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=48912b7604413a90bb1b5ce1d84326fd237b3e6d;p=clang AST: Don't assume two zero sized objects live at different addresses Zero sized objects may overlap with each other or any other object. This fixes PR21786. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@223852 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 28913385f0..acf78efad6 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1422,6 +1422,12 @@ static bool IsWeakLValue(const LValue &Value) { return Decl && Decl->isWeak(); } +static bool isZeroSized(const LValue &Value) { + const ValueDecl *Decl = GetLValueBaseDecl(Value); + return Decl && isa(Decl) && + Decl->getASTContext().getTypeSize(Decl->getType()) == 0; +} + static bool EvalPointerValueAsBool(const APValue &Value, bool &Result) { // A null base expression indicates a null pointer. These are always // evaluatable, and they are false unless the offset is zero. @@ -6979,6 +6985,10 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { (RHSValue.Base && RHSValue.Offset.isZero() && isOnePastTheEndOfCompleteObject(Info.Ctx, LHSValue))) 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)) + return Error(E); // Pointers with different bases cannot represent the same object. // (Note that clang defaults to -fmerge-all-constants, which can // lead to inconsistent results for comparisons involving the address diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index d50dd0bd72..9a650087f9 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -1955,3 +1955,9 @@ namespace EmptyClass { constexpr E2 e2b(e2); // expected-error {{constant expression}} expected-note{{read of non-const}} expected-note {{in call}} constexpr E3 e3b(e3); } + +namespace PR21786 { + extern void (*start[])(); + extern void (*end[])(); + static_assert(&start != &end, ""); // expected-error {{constant expression}} +}