]> granicus.if.org Git - clang/commitdiff
AST: Incomplete types might be zero sized
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 11 Dec 2014 19:36:24 +0000 (19:36 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 11 Dec 2014 19:36:24 +0000 (19:36 +0000)
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

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

index acf78efad6602d265aa4a667d2ddae5db9c79f72..417f7931df47a6b6acd03b22db56a88065250fa8 100644 (file)
@@ -1424,8 +1424,11 @@ static bool IsWeakLValue(const LValue &Value) {
 
 static bool isZeroSized(const LValue &Value) {
   const ValueDecl *Decl = GetLValueBaseDecl(Value);
-  return Decl && isa<VarDecl>(Decl) &&
-         Decl->getASTContext().getTypeSize(Decl->getType()) == 0;
+  if (Decl && isa<VarDecl>(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
index 9a650087f9a8b881e9090bae506635f55cf86c4a..5fb6f2c5f81c5bed2b3ee12960faea3a43f152b9 100644 (file)
@@ -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}}
 }