[cfe-commits] r143204 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Expr.h lib/AST/ExprConstant.cpp test/CodeGenCXX/static-data-member.cpp test/SemaCXX/constant-expression-cxx11.cpp

Richard Smith richard at metafoo.co.uk
Fri Oct 28 16:30:10 PDT 2011


Hi Chad,

Thanks for the excellent testcase! Fixed in r143250.

On Fri, October 28, 2011 21:21, Chad Rosier wrote:
> Hi Richard,
> I'm seeing assertion failures on some of our testers, which bisected to this
> revision.
>
> Assertion failed: (E->isRValue() && E->getType()->isRealFloatingType()),
> function EvaluateFloat, file
> /Users/mcrosier/llvm-clean/llvm/tools/clang/lib/AST/ExprConstant.cpp, line
> 2203.
> 0  clang             0x0000000109bb1c52 _ZL15PrintStackTracePv + 34 1  clang
> 0x0000000109bb2179 _ZL13SignalHandleri + 697
> 2  libsystem_c.dylib 0x00007fff8d815cfa _sigtramp + 26
> 3  libsystem_c.dylib 0x000000010a5ef278 _sigtramp + 18446603342611060120
> 4  clang             0x0000000109bb1ea6 abort + 22
> 5  clang             0x0000000109bb1e65 __assert_rtn + 53
> 6  clang             0x00000001090f7b6f (anonymous
> namespace)::FloatExprEvaluator::VisitBinaryOperator(clang::BinaryOperator
> const*) + 607 7  clang             0x00000001090f71e1
> clang::StmtVisitorBase<clang::make_const_ptr, (anonymous
> namespace)::FloatExprEvaluator, bool>::Visit(clang::Stmt const*) + 2865
> 8  clang             0x00000001090f71be
> clang::StmtVisitorBase<clang::make_const_ptr, (anonymous
> namespace)::FloatExprEvaluator, bool>::Visit(clang::Stmt const*) + 2830
> 9  clang             0x00000001090f3841 (anonymous
> namespace)::IntExprEvaluator::VisitBinaryOperator(clang::BinaryOperator
> const*) + 2289 10 clang             0x00000001090f29e6
> clang::StmtVisitorBase<clang::make_const_ptr, (anonymous
> namespace)::IntExprEvaluator, bool>::Visit(clang::Stmt const*) + 6262
> 11 clang             0x00000001090ec885
> _ZL8EvaluateRN5clang7APValueERN12_GLOBAL__N_18EvalInfoEPKNS_4ExprE + 325
> 12 clang             0x00000001090ec645
> clang::Expr::Evaluate(clang::Expr::EvalResult&, clang::ASTContext const&)
> const + 69 13 clang             0x00000001090ed192
> clang::Expr::EvaluateAsBooleanCondition(bool&, clang::ASTContext const&)
> const + 50 14 clang             0x0000000108ee3fac (anonymous
> namespace)::CFGBuilder::Visit(clang::Stmt*, (anonymous
> namespace)::AddStmtChoice) + 10940
> 15 clang             0x0000000108ee5d57 (anonymous
> namespace)::CFGBuilder::VisitCompoundStmt(clang::CompoundStmt*) + 119
> 16 clang             0x0000000108ee4c68 (anonymous
> namespace)::CFGBuilder::Visit(clang::Stmt*, (anonymous
> namespace)::AddStmtChoice) + 14200
> 17 clang             0x0000000108edc4fb clang::CFG::buildCFG(clang::Decl
> const*, clang::Stmt*, clang::ASTContext*, clang::CFG::BuildOptions const&) +
> 1531
> 18 clang             0x0000000108ed90ed clang::AnalysisDeclContext::getCFG() +
> 77
> 19 clang             0x0000000108b7a966
> clang::sema::AnalysisBasedWarnings::IssueWarnings(clang::sema::AnalysisBasedW
> arnings::Policy, clang::sema::FunctionScopeInfo*, clang::Decl const*,
> clang::BlockExpr const*) + 2198
> 20 clang             0x0000000108b93c9f
> clang::Sema::PopFunctionOrBlockScope(clang::sema::AnalysisBasedWarnings::Poli
> cy const*, clang::Decl const*, clang::BlockExpr const*) + 95 21 clang
> 0x0000000108c243d6 clang::Sema::ActOnFinishFunctionBody(clang::Decl*,
> clang::Stmt*, bool) + 1510
> 22 clang             0x0000000108b68634
> clang::Parser::ParseFunctionStatementBody(clang::Decl*,
> clang::Parser::ParseScope&) + 244
> 23 clang             0x0000000108b75fe1
> clang::Parser::ParseFunctionDefinition(clang::Parser::ParsingDeclarator&,
> clang::Parser::ParsedTemplateInfo const&) + 2241
> 24 clang             0x0000000108b2813c
> clang::Parser::ParseDeclGroup(clang::Parser::ParsingDeclSpec&, unsigned int,
> bool, clang::SourceLocation*, clang::Parser::ForRangeInit*) + 1020 25 clang
> 0x0000000108b7519a
> clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsingDec
> lSpec&, clang::AccessSpecifier) + 858 26 clang             0x0000000108b75399
> clang::Parser::ParseDeclarationOrFunctionDefinition(clang::ParsedAttributes&,
> clang::AccessSpecifier) + 393
> 27 clang             0x0000000108b7434f
> clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRa
> nge&, clang::Parser::ParsingDeclSpec*) + 3295 28 clang
> 0x0000000108b735f7
> clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&) +
> 247
> 29 clang             0x0000000108b1e0ed clang::ParseAST(clang::Sema&, bool) +
> 317
> 30 clang             0x0000000108aec920 clang::CodeGenAction::ExecuteAction()
> + 1040
> 31 clang             0x00000001088fe48b
> clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 955
> 32 clang             0x00000001088e8318
> clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 2792
> 33 clang             0x00000001088e0aa3 cc1_main(char const**, char const**,
> char const*, void*) + 5219 34 clang             0x00000001088e475f main + 687
> 35 clang             0x00000001088df634 start + 52
>
>
> Here's a delta reduced test case:
>
>
>
> Reproduce with:
> clang -Os -arch i386 -c foo.i -o /dev/null
>
> Please take a moment to investigate.
>
>
> Regards,
> Chad
>
>
>
>
> On Oct 28, 2011, at 10:51 AM, Richard Smith wrote:
>
>
>> Author: rsmith
>> Date: Fri Oct 28 12:51:58 2011
>> New Revision: 143204
>>
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=143204&view=rev
>> Log:
>> Reinstate r142844 (reverted in r142872) now that lvalue-to-rvalue
>> conversions are present in all the necessary places:
>>
>> In constant expression evaluation, evaluate lvalues as lvalues and rvalues
>> as rvalues. Remove special case for caching reference initialization and fix
>> a cyclic initialization crash in the process.
>>
>> Modified:
>> cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/include/clang/AST/Expr.h
>> cfe/trunk/lib/AST/ExprConstant.cpp
>> cfe/trunk/test/CodeGenCXX/static-data-member.cpp
>> cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
>>
>> Modified: cfe/trunk/include/clang/AST/ASTContext.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.
>> h?rev=143204&r1=143203&r2=143204&view=diff
>> ===========================================================================
>> ===
>> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
>> +++ cfe/trunk/include/clang/AST/ASTContext.h Fri Oct 28 12:51:58 2011
>> @@ -1274,7 +1274,7 @@
>> CanQualType getCanonicalParamType(QualType T) const;
>>
>>
>> /// \brief Determine whether the given types are equivalent.
>> -  bool hasSameType(QualType T1, QualType T2) {
>> +  bool hasSameType(QualType T1, QualType T2) const {
>> return getCanonicalType(T1) == getCanonicalType(T2); }
>>
>>
>> @@ -1294,7 +1294,7 @@
>>
>>
>> /// \brief Determine whether the given types are equivalent after
>> /// cvr-qualifiers have been removed.
>> -  bool hasSameUnqualifiedType(QualType T1, QualType T2) {
>> +  bool hasSameUnqualifiedType(QualType T1, QualType T2) const {
>> return getCanonicalType(T1).getTypePtr() ==
>> getCanonicalType(T2).getTypePtr(); }
>>
>>
>> Modified: cfe/trunk/include/clang/AST/Expr.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=
>> 143204&r1=143203&r2=143204&view=diff
>> ============================================================================
>> ==
>> --- cfe/trunk/include/clang/AST/Expr.h (original)
>> +++ cfe/trunk/include/clang/AST/Expr.h Fri Oct 28 12:51:58 2011
>> @@ -465,7 +465,8 @@
>> /// Evaluate - Return true if this is a constant which we can fold using
>> /// any crazy technique (that has nothing to do with language standards)
>> that /// we want to.  If this function returns true, it returns the folded
>> constant -  /// in Result.
>> +  /// in Result. If this expression is a glvalue, an lvalue-to-rvalue
>> conversion +  /// will be applied.
>> bool Evaluate(EvalResult &Result, const ASTContext &Ctx) const;
>>
>> /// EvaluateAsBooleanCondition - Return true if this is a constant
>>
>>
>> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=
>> 143204&r1=143203&r2=143204&view=diff
>> ============================================================================
>> ==
>> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
>> +++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Oct 28 12:51:58 2011
>> @@ -148,10 +148,13 @@
>> if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(E)) return
>> CLE->isFileScope();
>>
>>
>> +  if (isa<MemberExpr>(E))
>> +    return false;
>> +
>> return true; }
>>
>>
>> -static bool EvalPointerValueAsBool(LValue& Value, bool& Result) {
>> +static bool EvalPointerValueAsBool(const LValue &Value, bool &Result) {
>> const Expr* Base = Value.Base;
>>
>> // A null base expression indicates a null pointer.  These are always
>> @@ -183,40 +186,44 @@
>> return true; }
>>
>>
>> -static bool HandleConversionToBool(const Expr* E, bool& Result,
>> -                                   EvalInfo &Info) {
>> -  if (E->getType()->isIntegralOrEnumerationType()) {
>> -    APSInt IntResult;
>> -    if (!EvaluateInteger(E, IntResult, Info))
>> -      return false;
>> -    Result = IntResult != 0;
>> +static bool HandleConversionToBool(const APValue &Val, bool &Result) {
>> +  switch (Val.getKind()) {
>> +  case APValue::Uninitialized:
>> +    return false;
>> +  case APValue::Int:
>> +    Result = Val.getInt().getBoolValue();
>> return true; -  } else if (E->getType()->isRealFloatingType()) {
>> -    APFloat FloatResult(0.0);
>> -    if (!EvaluateFloat(E, FloatResult, Info))
>> -      return false;
>> -    Result = !FloatResult.isZero();
>> +  case APValue::Float:
>> +    Result = !Val.getFloat().isZero();
>> return true; -  } else if (E->getType()->hasPointerRepresentation()) {
>> -    LValue PointerResult;
>> -    if (!EvaluatePointer(E, PointerResult, Info))
>> -      return false;
>> -    return EvalPointerValueAsBool(PointerResult, Result);
>> -  } else if (E->getType()->isAnyComplexType()) {
>> -    ComplexValue ComplexResult;
>> -    if (!EvaluateComplex(E, ComplexResult, Info))
>> -      return false;
>> -    if (ComplexResult.isComplexFloat()) {
>> -      Result = !ComplexResult.getComplexFloatReal().isZero() ||
>> -               !ComplexResult.getComplexFloatImag().isZero();
>> -    } else {
>> -      Result = ComplexResult.getComplexIntReal().getBoolValue() ||
>> -               ComplexResult.getComplexIntImag().getBoolValue();
>> -    }
>> +  case APValue::ComplexInt:
>> +    Result = Val.getComplexIntReal().getBoolValue() ||
>> +             Val.getComplexIntImag().getBoolValue();
>> +    return true;
>> +  case APValue::ComplexFloat:
>> +    Result = !Val.getComplexFloatReal().isZero() ||
>> +             !Val.getComplexFloatImag().isZero();
>> return true; +  case APValue::LValue:
>> +    {
>> +      LValue PointerResult;
>> +      PointerResult.setFrom(Val);
>> +      return EvalPointerValueAsBool(PointerResult, Result);
>> +    }
>> +  case APValue::Vector:
>> +    return false;
>> }
>>
>>
>> -  return false;
>> +  llvm_unreachable("unknown APValue kind");
>> +}
>> +
>> +static bool EvaluateAsBooleanCondition(const Expr *E, bool &Result,
>> +                                       EvalInfo &Info) {
>> +  assert(E->isRValue() && "missing lvalue-to-rvalue conv in bool
>> condition"); +  APValue Val;
>> +  if (!Evaluate(Val, Info, E))
>> +    return false;
>> +  return HandleConversionToBool(Val, Result);
>> }
>>
>>
>> static APSInt HandleFloatToIntCast(QualType DestType, QualType SrcType, @@
>> -263,6 +270,8 @@
>>
>>
>> /// Try to evaluate the initializer for a variable declaration.
>> static APValue *EvaluateVarDeclInit(EvalInfo &Info, const VarDecl *VD) { +
>> // FIXME: If this is a parameter to an active constexpr function call,
>> perform +  // substitution now.
>> if (isa<ParmVarDecl>(VD)) return 0;
>>
>> @@ -278,10 +287,11 @@
>>
>>
>> VD->setEvaluatingValue();
>>
>>
>> -  // FIXME: If the initializer isn't a constant expression, propagate up
>> any -  // diagnostic explaining why not.
>> Expr::EvalResult EResult;
>> -  if (Init->Evaluate(EResult, Info.Ctx) && !EResult.HasSideEffects)
>> +  EvalInfo InitInfo(Info.Ctx, EResult);
>> +  // FIXME: The caller will need to know whether the value was a constant
>> +  // expression. If not, we should propagate up a diagnostic.
>> +  if (Evaluate(EResult.Val, InitInfo, Init))
>> VD->setEvaluatedValue(EResult.Val);
>> else VD->setEvaluatedValue(APValue());
>> @@ -289,11 +299,92 @@
>> return VD->getEvaluatedValue(); }
>>
>>
>> -bool IsConstNonVolatile(QualType T) {
>> +static bool IsConstNonVolatile(QualType T) {
>> Qualifiers Quals = T.getQualifiers();
>> return Quals.hasConst() && !Quals.hasVolatile(); }
>>
>>
>> +bool HandleLValueToRValueConversion(EvalInfo &Info, QualType Type,
>> +                                    const LValue &LVal, APValue &RVal) {
>> +  const Expr *Base = LVal.Base;
>> +
>> +  // FIXME: Indirection through a null pointer deserves a diagnostic.
>> +  if (!Base)
>> +    return false;
>> +
>> +  // FIXME: Support accessing subobjects of objects of literal types. A
>> simple +  // byte offset is insufficient for C++11 semantics: we need to
>> know how the +  // reference was formed (which union member was named, for
>> instance). +  // FIXME: Support subobjects of StringLiteral and
>> PredefinedExpr.
>> +  if (!LVal.Offset.isZero())
>> +    return false;
>> +
>> +  const Decl *D = 0;
>> +
>> +  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
>> +    // If the lvalue has been cast to some other type, don't try to read
>> it. +    // FIXME: Could simulate a bitcast here.
>> +    if (!Info.Ctx.hasSameUnqualifiedType(Type, DRE->getType()))
>> +      return false;
>> +    D = DRE->getDecl();
>> +  }
>> +
>> +  // FIXME: Static data members accessed via a MemberExpr are represented
>> as +  // that MemberExpr. We should use the Decl directly instead.
>> +  if (const MemberExpr *ME = dyn_cast<MemberExpr>(Base)) {
>> +    if (!Info.Ctx.hasSameUnqualifiedType(Type, ME->getType()))
>> +      return false;
>> +    D = ME->getMemberDecl();
>> +    assert(!isa<FieldDecl>(D) && "shouldn't see fields here");
>> +  }
>> +
>> +  if (D) {
>> +    // In C++98, const, non-volatile integers initialized with ICEs are
>> ICEs.
>> +    // In C++11, constexpr, non-volatile variables initialized with
>> constant +    // expressions are constant expressions too.
>> +    // In C, such things can also be folded, although they are not ICEs.
>> +    //
>> +    // FIXME: Allow folding any const variable of literal type initialized
>> with +    // a constant expression. For now, we only allow variables with
>> integral and +    // floating types to be folded.
>> +    const VarDecl *VD = dyn_cast<VarDecl>(D);
>> +    if (!VD || !IsConstNonVolatile(VD->getType()) ||
>> +        (!Type->isIntegralOrEnumerationType() &&
>> !Type->isRealFloatingType()))
>> +      return false;
>> +
>> +    APValue *V = EvaluateVarDeclInit(Info, VD);
>> +    if (!V || V->isUninit())
>> +      return false;
>> +
>> +    if (!VD->getAnyInitializer()->isLValue()) {
>> +      RVal = *V;
>> +      return true;
>> +    }
>> +
>> +    // The declaration was initialized by an lvalue, with no
>> lvalue-to-rvalue +    // conversion. This happens when the declaration and
>> the lvalue should be +    // considered synonymous, for instance when
>> initializing an array of char +    // from a string literal. Continue as if
>> the initializer lvalue was the +    // value we were originally given.
>> +    Base = V->getLValueBase();
>> +    if (!V->getLValueOffset().isZero())
>> +      return false;
>> +  }
>> +
>> +  // FIXME: C++11: Support MaterializeTemporaryExpr in LValueExprEvaluator
>> and +  // here.
>> +
>> +  // In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating
>> the +  // initializer until now for such expressions. Such an expression
>> can't be +  // an ICE in C, so this only matters for fold.
>> +  if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(Base))
>> {
>> +    assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in
>> c++?"); +    return Evaluate(RVal, Info, CLE->getInitializer());
>> +  }
>> +
>> +  return false;
>> +}
>> +
>> namespace { class HasSideEffect : public ConstStmtVisitor<HasSideEffect, bool>
>> {
>> @@ -454,7 +545,7 @@
>> return DerivedError(E);
>>
>> bool cond; -    if (!HandleConversionToBool(E->getCond(), cond, Info))
>> +    if (!EvaluateAsBooleanCondition(E->getCond(), cond, Info))
>> return DerivedError(E);
>>
>> return StmtVisitorTy::Visit(cond ? E->getTrueExpr() : E->getFalseExpr()); @@
>> -462,10 +553,10 @@
>>
>>
>> RetTy VisitConditionalOperator(const ConditionalOperator *E) {
>> bool BoolResult; -    if (!HandleConversionToBool(E->getCond(), BoolResult,
>> Info))
>> +    if (!EvaluateAsBooleanCondition(E->getCond(), BoolResult, Info))
>> return DerivedError(E);
>>
>> -    Expr* EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr();
>> +    Expr *EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr();
>> return StmtVisitorTy::Visit(EvalExpr); }
>>
>>
>> @@ -477,6 +568,9 @@
>> return DerivedSuccess(*value, E); }
>>
>>
>> +  RetTy VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
>> +    return StmtVisitorTy::Visit(E->getInitializer());
>> +  }
>> RetTy VisitInitListExpr(const InitListExpr *E) {
>> if (Info.getLangOpts().CPlusPlus0x) { if (E->getNumInits() == 0) @@ -493,6
>> +587,28 @@
>> return DerivedValueInitialization(E); }
>>
>>
>> +  RetTy VisitCastExpr(const CastExpr *E) {
>> +    switch (E->getCastKind()) {
>> +    default:
>> +      break;
>> +
>> +    case CK_NoOp:
>> +      return StmtVisitorTy::Visit(E->getSubExpr());
>> +
>> +    case CK_LValueToRValue: {
>> +      LValue LVal;
>> +      if (EvaluateLValue(E->getSubExpr(), LVal, Info)) {
>> +        APValue RVal;
>> +        if (HandleLValueToRValueConversion(Info, E->getType(), LVal, RVal))
>>  +          return DerivedSuccess(RVal, E);
>> +      }
>> +      break;
>> +    }
>> +    }
>> +
>> +    return DerivedError(E);
>> +  }
>> +
>> /// Visit a value which is evaluated, but whose value is ignored.
>> void VisitIgnoredValue(const Expr *E) { APValue Scratch;
>> @@ -505,6 +621,23 @@
>>
>>
>> //===----------------------------------------------------------------------
>> ===//
>> // LValue Evaluation
>> +//
>> +// This is used for evaluating lvalues (in C and C++), xvalues (in C++11),
>> +// function designators (in C), decl references to void objects (in C), and
>>  +// temporaries (if building with -Wno-address-of-temporary).
>> +//
>> +// LValue evaluation produces values comprising a base expression of one of
>> the +// following types:
>> +//  * DeclRefExpr
>> +//  * MemberExpr for a static member
>> +//  * CompoundLiteralExpr in C
>> +//  * StringLiteral
>> +//  * PredefinedExpr
>> +//  * ObjCEncodeExpr
>> +//  * AddrLabelExpr
>> +//  * BlockExpr
>> +//  * CallExpr for a MakeStringConstant builtin
>> +// plus an offset in bytes.
>> //===----------------------------------------------------------------------=
>> ==//
>> namespace { class LValueExprEvaluator @@ -530,6 +663,8 @@
>> return false; }
>>
>>
>> +  bool VisitVarDecl(const Expr *E, const VarDecl *VD);
>> +
>> bool VisitDeclRefExpr(const DeclRefExpr *E); bool VisitPredefinedExpr(const
>> PredefinedExpr *E) { return Success(E); }
>> bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); @@ -542,13
>> +677,13 @@
>> bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default:
>> -      return false;
>> +      return ExprEvaluatorBaseTy::VisitCastExpr(E);
>>
>>
>> -    case CK_NoOp:
>> case CK_LValueBitCast: return Visit(E->getSubExpr());
>>
>> -    // FIXME: Support CK_DerivedToBase and friends.
>> +    // FIXME: Support CK_DerivedToBase and CK_UncheckedDerivedToBase.
>> +    // Reuse PointerExprEvaluator::VisitCastExpr for these.
>> }
>> }
>>
>>
>> @@ -557,39 +692,52 @@
>> };
>> } // end anonymous namespace
>>
>>
>> +/// Evaluate an expression as an lvalue. This can be legitimately called
>> on +/// expressions which are not glvalues, in a few cases:
>> +///  * function designators in C,
>> +///  * "extern void" objects,
>> +///  * temporaries, if building with -Wno-address-of-temporary.
>> static bool EvaluateLValue(const Expr* E, LValue& Result, EvalInfo &Info) { +
>> assert((E->isGLValue() || E->getType()->isFunctionType() || +
>> E->getType()->isVoidType() || isa<CXXTemporaryObjectExpr>(E)) &&
>> +         "can't evaluate expression as an lvalue");
>> return LValueExprEvaluator(Info, Result).Visit(E); }
>>
>>
>> bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { -  if
>> (isa<FunctionDecl>(E->getDecl())) {
>> +  if (isa<FunctionDecl>(E->getDecl()))
>> return Success(E); -  } else if (const VarDecl* VD =
>> dyn_cast<VarDecl>(E->getDecl())) { -    if
>> (!VD->getType()->isReferenceType())
>> -      return Success(E);
>> -    // Reference parameters can refer to anything even if they have an
>> -    // "initializer" in the form of a default argument.
>> -    if (!isa<ParmVarDecl>(VD)) {
>> -      // FIXME: Check whether VD might be overridden!
>> +  if (const VarDecl* VD = dyn_cast<VarDecl>(E->getDecl()))
>> +    return VisitVarDecl(E, VD);
>> +  return Error(E);
>> +}
>>
>>
>> -      // Check for recursive initializers of references.
>> -      if (PrevDecl == VD)
>> -        return Error(E);
>> -      PrevDecl = VD;
>> -      if (const Expr *Init = VD->getAnyInitializer())
>> -        return Visit(Init);
>> -    }
>> -  }
>> +bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
>> +  if (!VD->getType()->isReferenceType())
>> +    return Success(E);
>> +
>> +  APValue *V = EvaluateVarDeclInit(Info, VD);
>> +  if (V && !V->isUninit())
>> +    return Success(*V, E);
>>
>>
>> -  return ExprEvaluatorBaseTy::VisitDeclRefExpr(E);
>> +  return Error(E);
>> }
>>
>>
>> bool LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr
>> *E) {
>> +  assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in
>> c++?"); +  // Defer visiting the literal until the lvalue-to-rvalue
>> conversion. We can +  // only see this when folding in C, so there's no
>> standard to follow here. return Success(E); }
>>
>>
>> bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { +  //
>> Handle static data members.
>> +  if (const VarDecl *VD = dyn_cast<VarDecl>(E->getMemberDecl())) {
>> +    VisitIgnoredValue(E->getBase());
>> +    return VisitVarDecl(E, VD);
>> +  }
>> +
>> QualType Ty;
>> if (E->isArrow()) { if (!EvaluatePointer(E->getBase(), Result, Info)) @@
>> -617,6 +765,10 @@
>> }
>>
>>
>> bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr
>> *E) {
>> +  // FIXME: Deal with vectors as array subscript bases.
>> +  if (E->getBase()->getType()->isVectorType())
>> +    return false;
>> +
>> if (!EvaluatePointer(E->getBase(), Result, Info)) return false;
>>
>> @@ -684,7 +836,7 @@
>> } // end anonymous namespace
>>
>>
>> static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info)
>> {
>> -  assert(E->getType()->hasPointerRepresentation());
>> +  assert(E->isRValue() && E->getType()->hasPointerRepresentation());
>> return PointerExprEvaluator(Info, Result).Visit(E); }
>>
>>
>> @@ -740,7 +892,6 @@
>> default:
>> break;
>>
>> -  case CK_NoOp:
>> case CK_BitCast: case CK_CPointerToObjCPointerCast: case
>> CK_BlockPointerToObjCPointerCast:
>> @@ -810,7 +961,7 @@
>> return EvaluateLValue(SubExpr, Result, Info); }
>>
>>
>> -  return false;
>> +  return ExprEvaluatorBaseTy::VisitCastExpr(E);
>> }
>>
>>
>> bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { @@ -852,7
>> +1003,6 @@
>> bool VisitUnaryReal(const UnaryOperator *E) { return Visit(E->getSubExpr());
>> }
>> bool VisitCastExpr(const CastExpr* E); -    bool
>> VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
>> bool VisitInitListExpr(const InitListExpr *E); bool VisitUnaryImag(const
>> UnaryOperator *E);
>> // FIXME: Missing: unary -, unary ~, binary add/sub/mul/div,
>> @@ -864,8 +1014,7 @@
>> } // end anonymous namespace
>>
>>
>> static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info)
>> {
>> -  if (!E->getType()->isVectorType())
>> -    return false;
>> +  assert(E->isRValue() && E->getType()->isVectorType() &&"not a vector
>> rvalue"); return VectorExprEvaluator(Info, Result).Visit(E); }
>>
>>
>> @@ -927,20 +1076,12 @@
>> }
>> return Success(Elts, E); }
>> -  case CK_LValueToRValue:
>> -  case CK_NoOp:
>> -    return Visit(SE);
>> default:
>> -    return Error(E);
>> +    return ExprEvaluatorBaseTy::VisitCastExpr(E);
>> }
>> }
>>
>>
>> bool -VectorExprEvaluator::VisitCompoundLiteralExpr(const
>> CompoundLiteralExpr *E) {
>> -  return Visit(E->getInitializer());
>> -}
>> -
>> -bool
>> VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
>> const VectorType *VT = E->getType()->castAs<VectorType>(); unsigned NumInits
>> = E->getNumInits();
>> @@ -1022,6 +1163,10 @@
>>
>>
>> //===----------------------------------------------------------------------
>> ===//
>> // Integer Evaluation
>> +//
>> +// As a GNU extension, we support casting pointers to sufficiently-wide
>> integer +// types and back in constant folding. Integer values are thus
>> represented +// either as an integer-valued APValue, or as an lvalue-valued
>> APValue.
>> //===----------------------------------------------------------------------=
>> ==//
>>
>>
>> namespace { @@ -1105,8 +1250,7 @@
>> }
>> bool VisitMemberExpr(const MemberExpr *E) { if (CheckReferencedDecl(E,
>> E->getMemberDecl())) {
>> -      // Conservatively assume a MemberExpr will have side-effects
>> -      Info.EvalStatus.HasSideEffects = true;
>> +      VisitIgnoredValue(E->getBase());
>> return true; }
>>
>>
>> @@ -1161,14 +1305,20 @@
>> };
>> } // end anonymous namespace
>>
>>
>> +/// EvaluateIntegerOrLValue - Evaluate an rvalue integral-typed
>> expression, and +/// produce either the integer value or a pointer.
>> +///
>> +/// GCC has a heinous extension which folds casts between pointer types and
>>  +/// pointer-sized integral types. We support this by allowing the
>> evaluation of +/// an integer rvalue to produce a pointer (represented as an
>> lvalue) instead. +/// Some simple arithmetic on such values is supported
>> (they are treated much
>> +/// like char*).
>> static bool EvaluateIntegerOrLValue(const Expr* E, APValue &Result, EvalInfo
>> &Info) {
>> -  assert(E->getType()->isIntegralOrEnumerationType());
>> +  assert(E->isRValue() && E->getType()->isIntegralOrEnumerationType());
>> return IntExprEvaluator(Info, Result).Visit(E); }
>>
>>
>> static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info)
>> {
>> -  assert(E->getType()->isIntegralOrEnumerationType());
>> -
>> APValue Val;
>> if (!EvaluateIntegerOrLValue(E, Val, Info) || !Val.isInt()) return false; @@
>> -1197,18 +1347,6 @@
>> return Success(Val, E); }
>> }
>> -
>> -  // In C++, const, non-volatile integers initialized with ICEs are ICEs.
>> -  // In C, they can also be folded, although they are not ICEs.
>> -  if (IsConstNonVolatile(E->getType())) {
>> -    if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
>> -      APValue *V = EvaluateVarDeclInit(Info, VD);
>> -      if (V && V->isInt())
>> -        return Success(V->getInt(), E);
>> -    }
>> -  }
>> -
>> -  // Otherwise, random variable references are not constants.
>> return false; }
>>
>>
>> @@ -1411,6 +1549,9 @@
>> }
>>
>>
>> bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { +  if
>> (E->isAssignmentOp())
>> +    return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice,
>> E);
>> +
>> if (E->getOpcode() == BO_Comma) { VisitIgnoredValue(E->getLHS());
>> return Visit(E->getRHS()); @@ -1421,20 +1562,20 @@
>> // necessarily integral
>> bool lhsResult, rhsResult;
>>
>> -    if (HandleConversionToBool(E->getLHS(), lhsResult, Info)) {
>> +    if (EvaluateAsBooleanCondition(E->getLHS(), lhsResult, Info)) {
>> // We were able to evaluate the LHS, see if we can get away with not
>> // evaluating the RHS: 0 && X -> 0, 1 || X -> 1
>> if (lhsResult == (E->getOpcode() == BO_LOr)) return Success(lhsResult, E);
>>
>> -      if (HandleConversionToBool(E->getRHS(), rhsResult, Info)) {
>> +      if (EvaluateAsBooleanCondition(E->getRHS(), rhsResult, Info)) {
>> if (E->getOpcode() == BO_LOr) return Success(lhsResult || rhsResult, E); else
>> return Success(lhsResult && rhsResult, E); }
>> } else {
>> -      if (HandleConversionToBool(E->getRHS(), rhsResult, Info)) {
>> +      if (EvaluateAsBooleanCondition(E->getRHS(), rhsResult, Info)) {
>> // We can't evaluate the LHS; however, sometimes the result
>> // is determined by the RHS: X && 0 -> 0, X || 1 -> 1.
>> if (rhsResult == (E->getOpcode() == BO_LOr) || @@ -1590,58 +1731,60 @@
>> }
>>
>>
>> // The LHS of a constant expr is always evaluated and needed.
>> -  if (!Visit(E->getLHS()))
>> +  APValue LHSVal;
>> +  if (!EvaluateIntegerOrLValue(E->getLHS(), LHSVal, Info))
>> return false; // error in subexpression.
>>
>> -  APValue RHSVal;
>> -  if (!EvaluateIntegerOrLValue(E->getRHS(), RHSVal, Info))
>> +  if (!Visit(E->getRHS()))
>> return false; +  APValue &RHSVal = Result;
>>
>>
>> // Handle cases like (unsigned long)&a + 4.
>> -  if (E->isAdditiveOp() && Result.isLValue() && RHSVal.isInt()) {
>> -    CharUnits Offset = Result.getLValueOffset();
>> +  if (E->isAdditiveOp() && LHSVal.isLValue() && RHSVal.isInt()) {
>> +    CharUnits Offset = LHSVal.getLValueOffset();
>> CharUnits AdditionalOffset = CharUnits::fromQuantity(
>> RHSVal.getInt().getZExtValue());
>> if (E->getOpcode() == BO_Add) Offset += AdditionalOffset;
>> else Offset -= AdditionalOffset;
>> -    Result = APValue(Result.getLValueBase(), Offset);
>> +    Result = APValue(LHSVal.getLValueBase(), Offset);
>> return true; }
>>
>>
>> // Handle cases like 4 + (unsigned long)&a
>> if (E->getOpcode() == BO_Add && -        RHSVal.isLValue() && Result.isInt())
>> {
>> +        RHSVal.isLValue() && LHSVal.isInt()) {
>> CharUnits Offset = RHSVal.getLValueOffset();
>> -    Offset += CharUnits::fromQuantity(Result.getInt().getZExtValue());
>> +    Offset += CharUnits::fromQuantity(LHSVal.getInt().getZExtValue());
>> Result = APValue(RHSVal.getLValueBase(), Offset);
>> return true; }
>>
>>
>> // All the following cases expect both operands to be an integer
>> -  if (!Result.isInt() || !RHSVal.isInt())
>> +  if (!LHSVal.isInt() || !RHSVal.isInt())
>> return false;
>>
>> -  APSInt& RHS = RHSVal.getInt();
>> +  APSInt &LHS = LHSVal.getInt();
>> +  APSInt &RHS = RHSVal.getInt();
>>
>>
>> switch (E->getOpcode()) { default:
>> return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E); -
>> case BO_Mul: return Success(Result.getInt() * RHS, E); -  case BO_Add:
>> return Success(Result.getInt() + RHS, E); -  case BO_Sub: return
>> Success(Result.getInt() - RHS, E);
>> -  case BO_And: return Success(Result.getInt() & RHS, E);
>> -  case BO_Xor: return Success(Result.getInt() ^ RHS, E);
>> -  case BO_Or:  return Success(Result.getInt() | RHS, E);
>> +  case BO_Mul: return Success(LHS * RHS, E);
>> +  case BO_Add: return Success(LHS + RHS, E);
>> +  case BO_Sub: return Success(LHS - RHS, E);
>> +  case BO_And: return Success(LHS & RHS, E);
>> +  case BO_Xor: return Success(LHS ^ RHS, E);
>> +  case BO_Or:  return Success(LHS | RHS, E);
>> case BO_Div: if (RHS == 0) return Error(E->getOperatorLoc(),
>> diag::note_expr_divide_by_zero, E);
>> -    return Success(Result.getInt() / RHS, E);
>> +    return Success(LHS / RHS, E);
>> case BO_Rem: if (RHS == 0) return Error(E->getOperatorLoc(),
>> diag::note_expr_divide_by_zero, E);
>> -    return Success(Result.getInt() % RHS, E);
>> +    return Success(LHS % RHS, E);
>> case BO_Shl: { // During constant-folding, a negative shift is an opposite
>> shift. if (RHS.isSigned() && RHS.isNegative()) { @@ -1651,8 +1794,8 @@
>>
>>
>> shift_left:
>> unsigned SA -      = (unsigned)
>> RHS.getLimitedValue(Result.getInt().getBitWidth()-1);
>> -    return Success(Result.getInt() << SA, E);
>> +      = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1);
>> +    return Success(LHS << SA, E);
>> }
>> case BO_Shr: { // During constant-folding, a negative shift is an opposite
>> shift. @@ -1663,16 +1806,16 @@
>>
>>
>> shift_right:
>> unsigned SA = -      (unsigned)
>> RHS.getLimitedValue(Result.getInt().getBitWidth()-1);
>> -    return Success(Result.getInt() >> SA, E);
>> +      (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1);
>> +    return Success(LHS >> SA, E);
>> }
>>
>>
>> -  case BO_LT: return Success(Result.getInt() < RHS, E);
>> -  case BO_GT: return Success(Result.getInt() > RHS, E);
>> -  case BO_LE: return Success(Result.getInt() <= RHS, E);
>> -  case BO_GE: return Success(Result.getInt() >= RHS, E);
>> -  case BO_EQ: return Success(Result.getInt() == RHS, E);
>> -  case BO_NE: return Success(Result.getInt() != RHS, E);
>> +  case BO_LT: return Success(LHS < RHS, E);
>> +  case BO_GT: return Success(LHS > RHS, E);
>> +  case BO_LE: return Success(LHS <= RHS, E);
>> +  case BO_GE: return Success(LHS >= RHS, E);
>> +  case BO_EQ: return Success(LHS == RHS, E);
>> +  case BO_NE: return Success(LHS != RHS, E);
>> }
>> }
>>
>>
>> @@ -1833,7 +1976,7 @@
>> if (E->getOpcode() == UO_LNot) { // LNot's operand isn't necessarily an
>> integer, so we handle it specially. bool bres; -    if
>> (!HandleConversionToBool(E->getSubExpr(), bres, Info))
>> +    if (!EvaluateAsBooleanCondition(E->getSubExpr(), bres, Info))
>> return false; return Success(!bres, E); }
>> @@ -1842,8 +1985,9 @@
>> if (!E->getSubExpr()->getType()->isIntegralOrEnumerationType()) return false;
>>
>>
>> -  // Get the operand value into 'Result'.
>> -  if (!Visit(E->getSubExpr()))
>> +  // Get the operand value.
>> +  APValue Val;
>> +  if (!Evaluate(Val, Info, E->getSubExpr()))
>> return false;
>>
>> switch (E->getOpcode()) { @@ -1854,16 +1998,16 @@
>> case UO_Extension: // FIXME: Should extension allow i-c-e extension
>> expressions in its scope? // If so, we could clear the diagnostic ID.
>> -    return true;
>> +    return Success(Val, E);
>> case UO_Plus: -    // The result is always just the subexpr.
>> -    return true;
>> +    // The result is just the value.
>> +    return Success(Val, E);
>> case UO_Minus: -    if (!Result.isInt()) return false;
>> -    return Success(-Result.getInt(), E);
>> +    if (!Val.isInt()) return false;
>> +    return Success(-Val.getInt(), E);
>> case UO_Not: -    if (!Result.isInt()) return false;
>> -    return Success(~Result.getInt(), E);
>> +    if (!Val.isInt()) return false;
>> +    return Success(~Val.getInt(), E);
>> }
>> }
>>
>>
>> @@ -1918,7 +2062,7 @@
>>
>>
>> case CK_LValueToRValue: case CK_NoOp: -    return Visit(E->getSubExpr());
>> +    return ExprEvaluatorBaseTy::VisitCastExpr(E);
>>
>>
>> case CK_MemberPointerToBoolean: case CK_PointerToBoolean: @@ -1927,7 +2071,7
>> @@
>> case CK_FloatingComplexToBoolean: case CK_IntegralComplexToBoolean: { bool
>> BoolResult;
>> -    if (!HandleConversionToBool(SubExpr, BoolResult, Info))
>> +    if (!EvaluateAsBooleanCondition(SubExpr, BoolResult, Info))
>> return false; return Success(BoolResult, E); }
>> @@ -2050,15 +2194,13 @@
>> bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const
>> UnaryOperator *E);
>>
>>
>> -  bool VisitDeclRefExpr(const DeclRefExpr *E);
>> -
>> // FIXME: Missing: array subscript of vector, member of vector,
>> //                 ImplicitValueInitExpr
>> };
>> } // end anonymous namespace
>>
>>
>> static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) {
>>  -  assert(E->getType()->isRealFloatingType());
>> +  assert(E->isRValue() && E->getType()->isRealFloatingType());
>> return FloatExprEvaluator(Info, Result).Visit(E); }
>>
>>
>> @@ -2141,21 +2283,6 @@
>> }
>> }
>>
>>
>> -bool FloatExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
>> -  if (ExprEvaluatorBaseTy::VisitDeclRefExpr(E))
>> -    return true;
>> -
>> -  const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl());
>> -  if (VD && IsConstNonVolatile(VD->getType())) {
>> -    APValue *V = EvaluateVarDeclInit(Info, VD);
>> -    if (V && V->isFloat()) {
>> -      Result = V->getFloat();
>> -      return true;
>> -    }
>> -  }
>> -  return false;
>> -}
>> -
>> bool FloatExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { if
>> (E->getSubExpr()->getType()->isAnyComplexType()) {
>> ComplexValue CV;
>> @@ -2245,11 +2372,7 @@
>>
>>
>> switch (E->getCastKind()) { default:
>> -    return false;
>> -
>> -  case CK_LValueToRValue:
>> -  case CK_NoOp:
>> -    return Visit(SubExpr);
>> +    return ExprEvaluatorBaseTy::VisitCastExpr(E);
>>
>>
>> case CK_IntegralToFloating: { APSInt IntResult;
>> @@ -2317,7 +2440,7 @@
>>
>>
>> static bool EvaluateComplex(const Expr *E, ComplexValue &Result, EvalInfo
>> &Info) {
>> -  assert(E->getType()->isAnyComplexType());
>> +  assert(E->isRValue() && E->getType()->isAnyComplexType());
>> return ComplexExprEvaluator(Info, Result).Visit(E); }
>>
>>
>> @@ -2390,7 +2513,7 @@
>>
>>
>> case CK_LValueToRValue: case CK_NoOp: -    return Visit(E->getSubExpr());
>> +    return ExprEvaluatorBaseTy::VisitCastExpr(E);
>>
>>
>> case CK_Dependent: case CK_GetObjCProperty: @@ -2634,27 +2757,28 @@
>> //===----------------------------------------------------------------------=
>> ==//
>>
>>
>> static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { -  if
>> (E->getType()->isVectorType()) {
>> +  // In C, function designators are not lvalues, but we evaluate them as if
>> they +  // are.
>> +  if (E->isGLValue() || E->getType()->isFunctionType()) {
>> +    LValue LV;
>> +    if (!EvaluateLValue(E, LV, Info))
>> +      return false;
>> +    LV.moveInto(Result);
>> +  } else if (E->getType()->isVectorType()) {
>> if (!EvaluateVector(E, Result, Info)) return false; } else if
>> (E->getType()->isIntegralOrEnumerationType()) {
>> if (!IntExprEvaluator(Info, Result).Visit(E)) return false; -    if
>> (Result.isLValue() &&
>> -        !IsGlobalLValue(Result.getLValueBase()))
>> -      return false;
>> } else if (E->getType()->hasPointerRepresentation()) {
>> LValue LV;
>> if (!EvaluatePointer(E, LV, Info)) return false; -    if
>> (!IsGlobalLValue(LV.Base))
>> -      return false;
>> LV.moveInto(Result);
>> } else if (E->getType()->isRealFloatingType()) {
>> llvm::APFloat F(0.0);
>> if (!EvaluateFloat(E, F, Info)) return false; -
>> Result = APValue(F);
>> } else if (E->getType()->isAnyComplexType()) {
>> ComplexValue C;
>> @@ -2667,36 +2791,50 @@
>> return true; }
>>
>>
>> +
>> /// Evaluate - Return true if this is a constant which we can fold using
>> /// any crazy technique (that has nothing to do with language standards)
>> that /// we want to.  If this function returns true, it returns the folded
>> constant -/// in Result.
>> +/// in Result. If this expression is a glvalue, an lvalue-to-rvalue
>> conversion +/// will be applied to the result.
>> bool Expr::Evaluate(EvalResult &Result, const ASTContext &Ctx) const {
>> EvalInfo Info(Ctx, Result);
>> -  return ::Evaluate(Result.Val, Info, this);
>> +
>> +  if (!::Evaluate(Result.Val, Info, this))
>> +    return false;
>> +
>> +  if (isGLValue()) {
>> +    LValue LV;
>> +    LV.setFrom(Result.Val);
>> +    return HandleLValueToRValueConversion(Info, getType(), LV, Result.Val);
>>  +  }
>> +
>> +  // FIXME: We don't allow expressions to fold to pointers or references to
>>  +  // locals. Code which calls Evaluate() isn't ready for that yet.
>> +  return !Result.Val.isLValue() ||
>> IsGlobalLValue(Result.Val.getLValueBase());
>> }
>>
>>
>> bool Expr::EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx)
>> const { -  EvalStatus Scratch;
>> -  EvalInfo Info(Ctx, Scratch);
>> -
>> -  return HandleConversionToBool(this, Result, Info);
>> +  EvalResult Scratch;
>> +  return Evaluate(Scratch, Ctx) && HandleConversionToBool(Scratch.Val,
>> Result);
>> }
>>
>>
>> bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx) const { -
>> EvalStatus Scratch;
>> -  EvalInfo Info(Ctx, Scratch);
>> -
>> -  return EvaluateInteger(this, Result, Info) && !Scratch.HasSideEffects;
>> +  EvalResult ExprResult;
>> +  if (!Evaluate(ExprResult, Ctx) || ExprResult.HasSideEffects ||
>> +      !ExprResult.Val.isInt()) {
>> +    return false;
>> +  }
>> +  Result = ExprResult.Val.getInt();
>> +  return true;
>> }
>>
>>
>> bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx)
>> const { EvalInfo Info(Ctx, Result);
>>
>>
>> LValue LV;
>> -  if (EvaluateLValue(this, LV, Info) &&
>> -      !Result.HasSideEffects &&
>> +  if (EvaluateLValue(this, LV, Info) && !Result.HasSideEffects &&
>> IsGlobalLValue(LV.Base)) {
>> LV.moveInto(Result.Val);
>> return true; @@ -3193,11 +3331,7 @@
>> if (Loc) *Loc = d.Loc; return false; }
>> -  EvalResult EvalResult;
>> -  if (!Evaluate(EvalResult, Ctx))
>> +  if (!EvaluateAsInt(Result, Ctx))
>> llvm_unreachable("ICE cannot be evaluated!"); -
>> assert(!EvalResult.HasSideEffects && "ICE with side effects!"); -
>> assert(EvalResult.Val.isInt() && "ICE that isn't integer!"); -  Result =
>> EvalResult.Val.getInt();
>> return true; }
>>
>>
>> Modified: cfe/trunk/test/CodeGenCXX/static-data-member.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/static-data-m
>> ember.cpp?rev=143204&r1=143203&r2=143204&view=diff
>> ===========================================================================
>> ===
>> --- cfe/trunk/test/CodeGenCXX/static-data-member.cpp (original)
>> +++ cfe/trunk/test/CodeGenCXX/static-data-member.cpp Fri Oct 28 12:51:58
>> 2011
>> @@ -64,3 +64,17 @@
>> // CHECK-NEXT: br label
>> // CHECK:      ret void
>> }
>> +
>> +// Test that we can fold member lookup expressions which resolve to static
>> data +// members.
>> +namespace test4 {
>> +  struct A {
>> +    static const int n = 76;
>> +  };
>> +
>> +  int f(A *a) {
>> +    // CHECK: define i32 @_ZN5test41fEPNS_1AE
>> +    // CHECK: ret i32 76
>> +    return a->n;
>> +  }
>> +}
>>
>>
>> Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-express
>> ion-cxx11.cpp?rev=143204&r1=143203&r2=143204&view=diff
>> ===========================================================================
>> ===
>> --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
>> +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Fri Oct 28 12:51:58
>> 2011
>> @@ -26,3 +26,17 @@
>> }
>> }
>> }
>> +
>> +extern int &Recurse1;
>> +int &Recurse2 = Recurse1, &Recurse1 = Recurse2;
>> +constexpr int &Recurse3 = Recurse2; // expected-error {{must be initialized
>> by a constant expression}} +
>> +namespace MemberEnum {
>> +  struct WithMemberEnum {
>> +    enum E { A = 42 };
>> +  } wme;
>> +  // FIXME: b's initializer is not treated as a constant expression yet,
>> but we +  // can at least fold it.
>> +  constexpr bool b = wme.A == 42;
>> +  int n[b];
>> +}
>>
>>
>>
>> _______________________________________________
>> cfe-commits mailing list cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>
>
>




More information about the cfe-commits mailing list