]> granicus.if.org Git - clang/commitdiff
AST: Don't assume two zero sized objects live at different addresses
authorDavid Majnemer <david.majnemer@gmail.com>
Tue, 9 Dec 2014 23:32:34 +0000 (23:32 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Tue, 9 Dec 2014 23:32:34 +0000 (23:32 +0000)
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

lib/AST/ExprConstant.cpp
test/SemaCXX/constant-expression-cxx11.cpp

index 28913385f0505d9f34981fb4ca05b032f9157c47..acf78efad6602d265aa4a667d2ddae5db9c79f72 100644 (file)
@@ -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<VarDecl>(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
index d50dd0bd728fb146196af59b3c8a09e31f3f615a..9a650087f9a8b881e9090bae506635f55cf86c4a 100644 (file)
@@ -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}}
+}