From 4f87062cb411d5a31cf39f1ac576bba4123930f2 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 27 Oct 2011 22:11:44 +0000 Subject: [PATCH] Fix some cases where a CK_IntegralCast was being used to convert an lvalue to an rvalue. An assertion to catch this is in ImpCastExprToType will follow, but vector operations currently trip over this (due to omitting the usual arithmetic conversions). Also add an assert to catch missing lvalue-to-rvalue conversions on the LHS of ->. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143155 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExprMember.cpp | 1 + lib/Sema/SemaStmt.cpp | 8 ++++++- lib/Sema/SemaTemplate.cpp | 11 ++++++++- test/SemaCXX/constant-expression-cxx11.cpp | 28 ++++++++++++++++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 test/SemaCXX/constant-expression-cxx11.cpp diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 5696e2386d..da099681cb 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -761,6 +761,7 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = 0) { + assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue"); return MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C), Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty, VK, OK); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index f35b359f57..6dcfbbab84 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -639,6 +639,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // If the LHS is not the same type as the condition, insert an implicit // cast. + // FIXME: In C++11, the value is a converted constant expression of the + // promoted type of the switch condition. + Lo = DefaultLvalueConversion(Lo).take(); Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).take(); CS->setLHS(Lo); @@ -716,8 +719,11 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, Hi->getLocStart(), diag::warn_case_value_overflow); - // If the LHS is not the same type as the condition, insert an implicit + // If the RHS is not the same type as the condition, insert an implicit // cast. + // FIXME: In C++11, the value is a converted constant expression of the + // promoted type of the switch condition. + Hi = DefaultLvalueConversion(Hi).take(); Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).take(); CR->setRHS(Hi); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index d2641888bd..de0193c61d 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -3743,8 +3743,16 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // enumeration type, integral promotions (4.5) and integral // conversions (4.7) are applied. QualType ParamType = InstantiatedParamType; - QualType ArgType = Arg->getType(); if (ParamType->isIntegralOrEnumerationType()) { + // FIXME: In C++11, the argument is a converted constant expression of the + // type of the template parameter. + ExprResult ArgResult = DefaultLvalueConversion(Arg); + if (ArgResult.isInvalid()) + return ExprError(); + Arg = ArgResult.take(); + + QualType ArgType = Arg->getType(); + // C++ [temp.arg.nontype]p1: // A template-argument for a non-type, non-template // template-parameter shall be one of: @@ -3868,6 +3876,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return Owned(Arg); } + QualType ArgType = Arg->getType(); DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction // C++0x [temp.arg.nontype]p5 bullets 2, 4 and 6 permit conversion diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp new file mode 100644 index 0000000000..89955701e6 --- /dev/null +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +template constexpr T id(const T &t) { return t; } + +struct MemberZero { + constexpr int zero() { return 0; } +}; + +namespace TemplateArgumentConversion { + template struct IntParam {}; + + using IntParam0 = IntParam<0>; + // FIXME: This should be accepted once we do constexpr function invocation. + using IntParam0 = IntParam; // expected-error {{not an integral constant expression}} + using IntParam0 = IntParam; // expected-error {{did you mean to call it with no arguments?}} expected-error {{not an integral constant expression}} +} + +namespace CaseStatements { + void f(int n) { + switch (n) { + // FIXME: Produce the 'add ()' fixit for this. + case MemberZero().zero: // desired-error {{did you mean to call it with no arguments?}} expected-error {{not an integer constant expression}} + // FIXME: This should be accepted once we do constexpr function invocation. + case id(1): // expected-error {{not an integer constant expression}} + return; + } + } +}