> 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.

Here's a current version of this patch; there were some recent changes
that caused merge conflicts.

-Eli
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h    (revision 45615)
+++ include/clang/AST/Expr.h    (working copy)
@@ -728,12 +728,15 @@
   /// synthesized compound expression.
   SourceLocation LParenLoc;
   Expr *Init;
+  bool FileScope;
 public:
-  CompoundLiteralExpr(SourceLocation lparenloc, QualType ty, Expr *init) : 
-    Expr(CompoundLiteralExprClass, ty), LParenLoc(lparenloc), Init(init) {}
+  CompoundLiteralExpr(SourceLocation lparenloc, QualType ty, Expr *init, bool 
fileScope) : 
+    Expr(CompoundLiteralExprClass, ty), LParenLoc(lparenloc), Init(init), 
FileScope(fileScope) {}
   
   const Expr *getInitializer() const { return Init; }
   Expr *getInitializer() { return Init; }
+
+  bool isFileScope() const { return FileScope; }
   
   SourceLocation getLParenLoc() const { return LParenLoc; }
   
Index: include/clang/Parse/Action.h
===================================================================
--- include/clang/Parse/Action.h        (revision 45615)
+++ include/clang/Parse/Action.h        (working copy)
@@ -401,7 +401,7 @@
     return 0;
   }
   
-  virtual ExprResult ActOnCompoundLiteral(SourceLocation LParen, TypeTy *Ty,
+  virtual ExprResult ActOnCompoundLiteral(Scope* S, SourceLocation LParen, 
TypeTy *Ty,
                                           SourceLocation RParen, ExprTy *Op) {
     return 0;
   }
Index: Sema/SemaExpr.cpp
===================================================================
--- Sema/SemaExpr.cpp   (revision 45615)
+++ Sema/SemaExpr.cpp   (working copy)
@@ -15,7 +15,8 @@
 #include "SemaUtil.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Expr.h"
-#include "clang/Parse/DeclSpec.h" 
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/LiteralSupport.h"
 #include "clang/Basic/SourceManager.h"
@@ -655,7 +656,7 @@
 }
 
 Action::ExprResult Sema::
-ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
+ActOnCompoundLiteral(Scope* S, SourceLocation LParenLoc, TypeTy *Ty,
                      SourceLocation RParenLoc, ExprTy *InitExpr) {
   assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
   QualType literalType = QualType::getFromOpaquePtr(Ty);
@@ -667,7 +668,7 @@
   if (CheckInitializer(literalExpr, literalType, false))
     return 0;
 
-  return new CompoundLiteralExpr(LParenLoc, literalType, literalExpr);
+  return new CompoundLiteralExpr(LParenLoc, literalType, literalExpr, 
S->getParent() == 0);
 }
 
 Action::ExprResult Sema::
@@ -1940,7 +1941,7 @@
   
   // Otherwise, create a compound literal expression as the base, and
   // iteratively process the offsetof designators.
-  Expr *Res = new CompoundLiteralExpr(SourceLocation(), ArgTy, 0);
+  Expr *Res = new CompoundLiteralExpr(SourceLocation(), ArgTy, 0, false);
   
   // offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are 
a
   // GCC extension, diagnose them.
Index: Sema/Sema.h
===================================================================
--- Sema/Sema.h (revision 45615)
+++ Sema/Sema.h (working copy)
@@ -422,8 +422,9 @@
   virtual ExprResult ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
                                    SourceLocation RParenLoc, ExprTy *Op);
                                    
-  virtual ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
-                                          SourceLocation RParenLoc, ExprTy 
*Op);
+  virtual ExprResult ActOnCompoundLiteral(Scope* S, SourceLocation LParenLoc,
+                                          TypeTy *Ty, SourceLocation RParenLoc,
+                                          ExprTy *Op);
   
   virtual ExprResult ActOnInitList(SourceLocation LParenLoc, 
                                    ExprTy **InitList, unsigned NumInit,
Index: Sema/SemaDecl.cpp
===================================================================
--- Sema/SemaDecl.cpp   (revision 45615)
+++ Sema/SemaDecl.cpp   (working copy)
@@ -354,6 +354,19 @@
 
 bool Sema::CheckSingleInitializer(Expr *&Init, bool isStatic, 
                                   QualType DeclType) {
+  // Get the type before calling CheckSingleAssignmentConstraints(), since
+  // it can promote the expression.
+  QualType InitType = Init->getType(); 
+  
+  AssignConvertType ConvTy = CheckSingleAssignmentConstraints(DeclType, Init);
+  if (DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType,
+                                  InitType, Init, "initializing"))
+    return true;
+
+  // 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;
@@ -363,14 +376,7 @@
     Diag(loc, diag::err_init_element_not_constant, Init->getSourceRange());
     return true;
   }
-  
-  // Get the type before calling CheckSingleAssignmentConstraints(), since
-  // it can promote the expression.
-  QualType InitType = Init->getType(); 
-  
-  AssignConvertType ConvTy = CheckSingleAssignmentConstraints(DeclType, Init);
-  return DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType,
-                                  InitType, Init, "initializing");
+  return false;
 }
 
 bool Sema::CheckInitExpr(Expr *expr, InitListExpr *IList, unsigned slot,
Index: AST/Expr.cpp
===================================================================
--- AST/Expr.cpp        (revision 45615)
+++ AST/Expr.cpp        (working copy)
@@ -418,6 +418,8 @@
     return cast<ParenExpr>(this)->getSubExpr()->hasStaticStorage();
   case ImplicitCastExprClass:
     return cast<ImplicitCastExpr>(this)->getSubExpr()->hasStaticStorage();
+  case CompoundLiteralExprClass:
+    return cast<CompoundLiteralExpr>(this)->isFileScope();
   case DeclRefExprClass: {
     const Decl *D = cast<DeclRefExpr>(this)->getDecl();
     if (const VarDecl *VD = dyn_cast<VarDecl>(D))
@@ -461,12 +463,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: {
@@ -474,6 +473,8 @@
     
     // C99 6.6p9
     if (Exp->getOpcode() == UnaryOperator::AddrOf) {
+      if (Exp->getSubExpr()->getType()->isFunctionType())
+        return true;
       if (!Exp->getSubExpr()->hasStaticStorage()) {
         if (Loc) *Loc = getLocStart();
         return false;
@@ -541,6 +542,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;
Index: AST/StmtSerialization.cpp
===================================================================
--- AST/StmtSerialization.cpp   (revision 45615)
+++ AST/StmtSerialization.cpp   (working copy)
@@ -392,13 +392,15 @@
   S.Emit(getType());
   S.Emit(getLParenLoc());
   S.EmitOwnedPtr(Init);
+  S.EmitBool(isFileScope());
 }
 
 CompoundLiteralExpr* CompoundLiteralExpr::CreateImpl(Deserializer& D) {
   QualType Q = QualType::ReadVal(D);
   SourceLocation L = SourceLocation::ReadVal(D);
   Expr* Init = D.ReadOwnedPtr<Expr>();
-  return new CompoundLiteralExpr(L, Q, Init);
+  bool fileScope = D.ReadBool();
+  return new CompoundLiteralExpr(L, Q, Init, fileScope);
 }
 
 void CompoundStmt::EmitImpl(Serializer& S) const {
Index: Driver/RewriteTest.cpp
===================================================================
--- Driver/RewriteTest.cpp      (revision 45615)
+++ Driver/RewriteTest.cpp      (working copy)
@@ -1322,7 +1322,7 @@
   InitListExpr *ILE = new InitListExpr(SourceLocation(), 
                                        &InitExprs[0], InitExprs.size(), 
                                        SourceLocation());
-  CompoundLiteralExpr *StrRep = new CompoundLiteralExpr(CFConstantStrType, 
ILE);
+  CompoundLiteralExpr *StrRep = new CompoundLiteralExpr(CFConstantStrType, 
ILE, false);
   // struct NSConstantString *
   expType = Context->getPointerType(StrRep->getType());
   Unop = new UnaryOperator(StrRep, UnaryOperator::AddrOf, expType, 
@@ -1455,7 +1455,7 @@
                                            &InitExprs[0], InitExprs.size(), 
                                            SourceLocation());
       CompoundLiteralExpr *SuperRep = new CompoundLiteralExpr(SourceLocation(),
-                                                              superType, ILE);
+                                                              superType, ILE, 
false);
       // struct objc_super *
       Expr *Unop = new UnaryOperator(SuperRep, UnaryOperator::AddrOf,
                                Context->getPointerType(SuperRep->getType()), 
@@ -1508,7 +1508,7 @@
                                            &InitExprs[0], InitExprs.size(), 
                                            SourceLocation());
       CompoundLiteralExpr *SuperRep = new CompoundLiteralExpr(SourceLocation(),
-                                                              superType, ILE);
+                                                              superType, ILE, 
false);
       // struct objc_super *
       Expr *Unop = new UnaryOperator(SuperRep, UnaryOperator::AddrOf,
                                Context->getPointerType(SuperRep->getType()), 
Index: Parse/ParseExpr.cpp
===================================================================
--- Parse/ParseExpr.cpp (revision 45615)
+++ Parse/ParseExpr.cpp (working copy)
@@ -976,7 +976,7 @@
       Result = ParseInitializer();
       ExprType = CompoundLiteral;
       if (!Result.isInvalid)
-        return Actions.ActOnCompoundLiteral(OpenLoc, Ty, RParenLoc, 
Result.Val);
+        return Actions.ActOnCompoundLiteral(CurScope, OpenLoc, Ty, RParenLoc, 
Result.Val);
     } else if (ExprType == CastExpr) {
       // Note that this doesn't parse the subsequence cast-expression, it just
       // returns the parsed type to the callee.
_______________________________________________
cfe-dev mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

Reply via email to