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(this)->getSubExpr()->hasStaticStorage(); case ImplicitCastExprClass: return cast(this)->getSubExpr()->hasStaticStorage(); + case CompoundLiteralExprClass: + return cast(this)->isFileScope(); case DeclRefExprClass: { const Decl *D = cast(this)->getDecl(); if (const VarDecl *VD = dyn_cast(D)) @@ -461,12 +463,9 @@ } case DeclRefExprClass: { const Decl *D = cast(this)->getDecl(); - // Accept address of function. - if (isa(D) || isa(D)) + if (isa(D)) return true; if (Loc) *Loc = getLocStart(); - if (isa(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(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(); - 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.