[cfe-commits] r144273 - in /cfe/trunk: lib/AST/ExprConstant.cpp test/SemaCXX/constant-expression-cxx11.cpp

Devang Patel dpatel at apple.com
Thu Nov 10 09:49:27 PST 2011


Richard,

I am reverting this patch because it is causing clang self-host build failure with following assertion. Please investigate.

Assertion failed: ((E->isGLValue() || E->getType()->isFunctionType() || E->getType()->isVoidType() || isa<CXXTemporaryObjectExpr>(E)) && "can't evaluate expression as an lvalue"), function EvaluateLValue, file /Volumes/Lalgate/clean/llvm/tools/clang/lib/AST/ExprConstant.cpp, line 1549.
0  clang             0x000000010b795a52 _ZL15PrintStackTracePv + 34
1  clang             0x000000010b796049 _ZL13SignalHandleri + 777
2  libsystem_c.dylib 0x00007fff84106cfa _sigtramp + 26
3  libsystem_c.dylib 0x00007f9b09a7dc80 _sigtramp + 18446743642159148960
4  clang             0x000000010b795c96 abort + 22
5  clang             0x000000010b795c57 __assert_rtn + 55
6  clang             0x000000010ac52b84 _ZL14EvaluateLValuePKN5clang4ExprERN12_GLOBAL__N_16LValueERNS3_8EvalInfoE + 132
7  clang             0x000000010ac5d115 (anonymous namespace)::IntExprEvaluator::VisitCallExpr(clang::CallExpr const*) + 1765
8  clang             0x000000010ac594d0 clang::StmtVisitorBase<clang::make_const_ptr, (anonymous namespace)::IntExprEvaluator, bool>::Visit(clang::Stmt const*) + 2000
9  clang             0x000000010ac50ec4 _ZL8EvaluateRN12_GLOBAL__N_17CCValueERNS_8EvalInfoEPKN5clang4ExprE + 388
10 clang             0x000000010ac50af2 clang::Expr::EvaluateAsRValue(clang::Expr::EvalResult&, clang::ASTContext const&) const + 306
11 clang             0x000000010ac521e9 clang::Expr::EvaluateAsBooleanCondition(bool&, clang::ASTContext const&) const + 57
12 clang             0x000000010aa2e21b (anonymous namespace)::CFGBuilder::Visit(clang::Stmt*, (anonymous namespace)::AddStmtChoice) + 11435
13 clang             0x000000010aa30137 (anonymous namespace)::CFGBuilder::VisitCompoundStmt(clang::CompoundStmt*) + 119
14 clang             0x000000010aa2efe4 (anonymous namespace)::CFGBuilder::Visit(clang::Stmt*, (anonymous namespace)::AddStmtChoice) + 14964
15 clang             0x000000010aa2626f clang::CFG::buildCFG(clang::Decl const*, clang::Stmt*, clang::ASTContext*, clang::CFG::BuildOptions const&) + 1519
16 clang             0x000000010aa22cbd clang::AnalysisDeclContext::getCFG() + 77
17 clang             0x000000010a6bdef5 clang::sema::AnalysisBasedWarnings::IssueWarnings(clang::sema::AnalysisBasedWarnings::Policy, clang::sema::FunctionScopeInfo*, clang::Decl const*, clang::BlockExpr const*) + 4149
18 clang             0x000000010a6d67af clang::Sema::PopFunctionOrBlockScope(clang::sema::AnalysisBasedWarnings::Policy const*, clang::Decl const*, clang::BlockExpr const*) + 95
19 clang             0x000000010a767cad clang::Sema::ActOnFinishFunctionBody(clang::Decl*, clang::Stmt*, bool) + 1501
20 clang             0x000000010a6ab204 clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&) + 244
21 clang             0x000000010a6b8d83 clang::Parser::ParseFunctionDefinition(clang::Parser::ParsingDeclarator&, clang::Parser::ParsedTemplateInfo const&) + 2259
22 clang             0x000000010a66aacc clang::Parser::ParseDeclGroup(clang::Parser::ParsingDeclSpec&, unsigned int, bool, clang::SourceLocation*, clang::Parser::ForRangeInit*) + 1068
23 clang             0x000000010a6b7efa clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsingDeclSpec&, clang::AccessSpecifier) + 858
24 clang             0x000000010a6b80f9 clang::Parser::ParseDeclarationOrFunctionDefinition(clang::ParsedAttributes&, clang::AccessSpecifier) + 393
25 clang             0x000000010a6b70af clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::Parser::ParsingDeclSpec*) + 3311
26 clang             0x000000010a6b6347 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&) + 247
27 clang             0x000000010a66079d clang::ParseAST(clang::Sema&, bool) + 317
28 clang             0x000000010a62e5f7 clang::CodeGenAction::ExecuteAction() + 1031
29 clang             0x000000010a434a9b clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 955
30 clang             0x000000010a41d4c8 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 2792
31 clang             0x000000010a414ce7 cc1_main(char const**, char const**, char const*, void*) + 5287
32 clang             0x000000010a419852 main + 706
33 clang             0x000000010a413834 start + 52
34 clang             0x0000000000000050 start + 18446744069242538064
Stack dump:

-
Devang


On Nov 10, 2011, at 1:31 AM, Richard Smith wrote:

> Author: rsmith
> Date: Thu Nov 10 03:31:24 2011
> New Revision: 144273
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=144273&view=rev
> Log:
> Constant expression evaluation: support for constexpr member functions.
> 
> Modified:
>    cfe/trunk/lib/AST/ExprConstant.cpp
>    cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
> 
> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=144273&r1=144272&r2=144273&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Nov 10 03:31:24 2011
> @@ -1029,8 +1029,9 @@
> }
> 
> /// Evaluate a function call.
> -static bool HandleFunctionCall(ArrayRef<const Expr*> Args, const Stmt *Body,
> -                               EvalInfo &Info, CCValue &Result) {
> +static bool HandleFunctionCall(const LValue *This, ArrayRef<const Expr*> Args,
> +                               const Stmt *Body, EvalInfo &Info,
> +                               CCValue &Result) {
>   // FIXME: Implement a proper call limit, along with a command-line flag.
>   if (Info.NumCalls >= 1000000 || Info.CallStackDepth >= 512)
>     return false;
> @@ -1039,16 +1040,15 @@
>   if (!EvaluateArgs(Args, ArgValues, Info))
>     return false;
> 
> -  // FIXME: Pass in 'this' for member functions.
> -  const LValue *This = 0;
>   CallStackFrame Frame(Info, This, ArgValues.data());
>   return EvaluateStmt(Result, Info, Body) == ESR_Returned;
> }
> 
> /// Evaluate a constructor call.
> -static bool HandleConstructorCall(ArrayRef<const Expr*> Args,
> +static bool HandleConstructorCall(const LValue &This,
> +                                  ArrayRef<const Expr*> Args,
>                                   const CXXConstructorDecl *Definition,
> -                                  EvalInfo &Info, const LValue &This,
> +                                  EvalInfo &Info,
>                                   APValue &Result) {
>   if (Info.NumCalls >= 1000000 || Info.CallStackDepth >= 512)
>     return false;
> @@ -1305,39 +1305,64 @@
>     const Expr *Callee = E->getCallee();
>     QualType CalleeType = Callee->getType();
> 
> -    // FIXME: Handle the case where Callee is a (parenthesized) MemberExpr for a
> -    // non-static member function.
> -    if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember))
> -      return DerivedError(E);
> -
> -    if (!CalleeType->isFunctionType() && !CalleeType->isFunctionPointerType())
> -      return DerivedError(E);
> -
> -    CCValue Call;
> -    if (!Evaluate(Call, Info, Callee) || !Call.isLValue() ||
> -        !Call.getLValueBase() || !Call.getLValueOffset().isZero())
> -      return DerivedError(Callee);
> -
>     const FunctionDecl *FD = 0;
> -    if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Call.getLValueBase()))
> -      FD = dyn_cast<FunctionDecl>(DRE->getDecl());
> -    else if (const MemberExpr *ME = dyn_cast<MemberExpr>(Call.getLValueBase()))
> +    LValue *This = 0, ThisVal;
> +    llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs());
> +
> +    // Extract function decl and 'this' pointer from the callee.
> +    if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) {
> +      const MemberExpr *ME = dyn_cast<MemberExpr>(Callee->IgnoreParens());
> +      // FIXME: Handle a BinaryOperator callee ('.*' or '->*').
> +      if (!ME)
> +        return DerivedError(Callee);
> +      if (ME->isArrow()) {
> +        if (!EvaluatePointer(ME->getBase(), ThisVal, Info))
> +          return DerivedError(ME);
> +      } else {
> +        if (!EvaluateLValue(ME->getBase(), ThisVal, Info))
> +          return DerivedError(ME);
> +      }
> +      This = &ThisVal;
>       FD = dyn_cast<FunctionDecl>(ME->getMemberDecl());
> -    if (!FD)
> -      return DerivedError(Callee);
> +      if (!FD)
> +        return DerivedError(ME);
> +    } else if (CalleeType->isFunctionPointerType()) {
> +      CCValue Call;
> +      if (!Evaluate(Call, Info, Callee) || !Call.isLValue() ||
> +          !Call.getLValueBase() || !Call.getLValueOffset().isZero())
> +        return DerivedError(Callee);
> +
> +      const Expr *Base = Call.getLValueBase();
> +
> +      if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base))
> +        FD = dyn_cast<FunctionDecl>(DRE->getDecl());
> +      else if (const MemberExpr *ME = dyn_cast<MemberExpr>(Base))
> +        FD = dyn_cast<FunctionDecl>(ME->getMemberDecl());
> +      if (!FD)
> +        return DerivedError(Callee);
> +
> +      // Overloaded operator calls to member functions are represented as normal
> +      // calls with 'this' as the first argument.
> +      const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
> +      if (MD && !MD->isStatic()) {
> +        if (!EvaluateLValue(Args[0], ThisVal, Info))
> +          return DerivedError(Args[0]);
> +        This = &ThisVal;
> +        Args = Args.slice(1);
> +      }
> 
> -    // Don't call function pointers which have been cast to some other type.
> -    if (!Info.Ctx.hasSameType(CalleeType->getPointeeType(), FD->getType()))
> -      return DerivedError(E);
> +      // Don't call function pointers which have been cast to some other type.
> +      if (!Info.Ctx.hasSameType(CalleeType->getPointeeType(), FD->getType()))
> +        return DerivedError(E);
> +    }
> 
>     const FunctionDecl *Definition;
>     Stmt *Body = FD->getBody(Definition);
>     CCValue CCResult;
>     APValue Result;
> -    llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs());
> 
>     if (Body && Definition->isConstexpr() && !Definition->isInvalidDecl() &&
> -        HandleFunctionCall(Args, Body, Info, CCResult) &&
> +        HandleFunctionCall(This, Args, Body, Info, CCResult) &&
>         CheckConstantExpression(CCResult, Result))
>       return DerivedSuccess(CCValue(Result, CCValue::GlobalValue()), E);
> 
> @@ -1890,8 +1915,8 @@
>       return Visit(ME->GetTemporaryExpr());
> 
>   llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs());
> -  return HandleConstructorCall(Args, cast<CXXConstructorDecl>(Definition),
> -                               Info, This, Result);
> +  return HandleConstructorCall(This, Args, cast<CXXConstructorDecl>(Definition),
> +                               Info, Result);
> }
> 
> static bool EvaluateRecord(const Expr *E, const LValue &This,
> 
> Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=144273&r1=144272&r2=144273&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
> +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Thu Nov 10 03:31:24 2011
> @@ -608,3 +608,35 @@
> static_assert_fold((&(u[1]) + 1 + 1)->b == 3, "");
> 
> }
> +
> +namespace Complex {
> +
> +class complex {
> +  int re, im;
> +public:
> +  constexpr complex(int re = 0, int im = 0) : re(re), im(im) {}
> +  constexpr complex(const complex &o) : re(o.re), im(o.im) {}
> +  constexpr complex operator-() const { return complex(-re, -im); }
> +  friend constexpr complex operator+(const complex &l, const complex &r) {
> +    return complex(l.re + r.re, l.im + r.im);
> +  }
> +  friend constexpr complex operator-(const complex &l, const complex &r) {
> +    return l + -r;
> +  }
> +  friend constexpr complex operator*(const complex &l, const complex &r) {
> +    return complex(l.re * r.re - l.im * r.im, l.re * r.im + l.im * r.re);
> +  }
> +  friend constexpr bool operator==(const complex &l, const complex &r) {
> +    return l.re == r.re && l.im == r.im;
> +  }
> +  constexpr int real() const { return re; }
> +  constexpr int imag() const { return im; }
> +};
> +
> +constexpr complex i = complex(0, 1);
> +constexpr complex k = (3 + 4*i) * (6 - 4*i);
> +static_assert_fold(k.real() == 34, "");
> +static_assert_fold(k.imag() == 12, "");
> +static_assert_fold(k - 34 == 12*i, "");
> +
> +}
> 
> 
> _______________________________________________
> 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