>From http://llvm.org/bugs/show_bug.cgi?id=1891; patch at
http://llvm.org/bugs/attachment.cgi?id=1318, and also attached (I
don't know if GMail will mangle it...).

Patch fixes testcases like:
static int *p = (int []){2, 4};

and

typedef struct Test {int a;int b;} Test;
static Test* ll = &(Test) {0,0};

so that they get through sema correctly.

This patch fixes a few underlying issues:

1. It was previously not possible to determine (AFAIK) whether a
CompoundLiteralExpr was file scope or not, so this patch propagates
that information from the parser.  This is the biggest change, but is
mostly mechanical.
2. It makes Expr::hasStaticStorage use that information when necessary.
3. It makes Expr::isConstantExpr deal with arrays that aren't
declarations (currently, that's just compound literals).
4. It changes the order of the checks in Sema::CheckSingleInitializer
so that any necessary implicit casts get added before checking for
whether an initializer is constant.

Expr::isConstantExpr definitely needs more work; it is currently
letting through some expressions that aren't constant, like:
static int r[2] = {1,2};
static int ss[2] = {3,4};
static int t = r-ss; // Wrong: Illegal per C99, and impossible to emit to LLVM
static int* zz = &r[t]; // Wrong: Obviously not constant

Expr::hasStaticStorage and Expr::isConstantExpr probably need to be
restructured to deal with cases like &r[t];

-Eli Friedman
Index: Sema/SemaDecl.cpp
===================================================================
--- Sema/SemaDecl.cpp   (revision 45425)
+++ Sema/SemaDecl.cpp   (working copy)
@@ -354,16 +354,6 @@
 
 bool Sema::CheckSingleInitializer(Expr *&Init, bool isStatic, 
                                   QualType DeclType) {
-  // FIXME: Remove the isReferenceType check and handle assignment
-  // to a reference.
-  SourceLocation loc;
-  if (isStatic && !DeclType->isReferenceType() &&
-      !Init->isConstantExpr(Context, &loc)) { // C99 6.7.8p4.
-    assert(loc.isValid() && "isConstantExpr didn't return a loc!");
-    Diag(loc, diag::err_init_element_not_constant, Init->getSourceRange());
-    return true;
-  }
-  
   AssignmentCheckResult result;
   // Get the type before calling CheckSingleAssignmentConstraints(), since
   // it can promote the expression.
@@ -405,6 +395,21 @@
          Init->getSourceRange());
     break;
   }
+
+  // This has to be done after checking for assignment
+  // compatibility because those checks might introduce a necessary
+  // implicit conversion (e.g. a static array isn't constant, but a
+  // pointer to a static array is constant).
+  // FIXME: Remove the isReferenceType check and handle assignment
+  // to a reference.
+  SourceLocation loc;
+  if (isStatic && !DeclType->isReferenceType() &&
+      !Init->isConstantExpr(Context, &loc)) { // C99 6.7.8p4.
+    assert(loc.isValid() && "isConstantExpr didn't return a loc!");
+    Diag(loc, diag::err_init_element_not_constant, Init->getSourceRange());
+    return true;
+  }
+
   return false;
 }
 
Index: AST/Expr.cpp
===================================================================
--- AST/Expr.cpp        (revision 45425)
+++ AST/Expr.cpp        (working copy)
@@ -461,12 +461,9 @@
   }
   case DeclRefExprClass: {
     const Decl *D = cast<DeclRefExpr>(this)->getDecl();
-    // Accept address of function.
-    if (isa<EnumConstantDecl>(D) || isa<FunctionDecl>(D))
+    if (isa<EnumConstantDecl>(D))
       return true;
     if (Loc) *Loc = getLocStart();
-    if (isa<VarDecl>(D))
-      return TR->isArrayType();
     return false;
   }
   case UnaryOperatorClass: {
@@ -541,6 +538,19 @@
       SubExpr = cast<ImplicitCastExpr>(this)->getSubExpr();
       CastLoc = getLocStart();
     }
+    if (SubExpr->getType()->isArrayType()) {
+      // FIXME: This check isn't strict enough: the fact that an array has 
static scope
+      // doesn't mean the address is computable at compile-time.
+      // FIXME: This code should be shared with the code for 
UnaryOperator::AddrOf.
+      if (!SubExpr->hasStaticStorage()) {
+        if (Loc) *Loc = getLocStart();
+        return false;
+      }
+      return true;
+    }
+    // FIXME: Only correct for C, AFAIK. (consider "static Func* f = obj->f;" 
in C++)
+    if (SubExpr->getType()->isFunctionType())
+      return true;
     if (!SubExpr->isConstantExpr(Ctx, Loc)) {
       if (Loc) *Loc = SubExpr->getLocStart();
       return false;
_______________________________________________
cfe-dev mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

Reply via email to