зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
2ce634dbb2
Коммит
4f87062cb4
|
@ -761,6 +761,7 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
|
||||||
QualType Ty,
|
QualType Ty,
|
||||||
ExprValueKind VK, ExprObjectKind OK,
|
ExprValueKind VK, ExprObjectKind OK,
|
||||||
const TemplateArgumentListInfo *TemplateArgs = 0) {
|
const TemplateArgumentListInfo *TemplateArgs = 0) {
|
||||||
|
assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue");
|
||||||
return MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C),
|
return MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C),
|
||||||
Member, FoundDecl, MemberNameInfo,
|
Member, FoundDecl, MemberNameInfo,
|
||||||
TemplateArgs, Ty, VK, OK);
|
TemplateArgs, Ty, VK, OK);
|
||||||
|
|
|
@ -639,6 +639,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
|
||||||
|
|
||||||
// If the LHS is not the same type as the condition, insert an implicit
|
// If the LHS is not the same type as the condition, insert an implicit
|
||||||
// cast.
|
// 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();
|
Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).take();
|
||||||
CS->setLHS(Lo);
|
CS->setLHS(Lo);
|
||||||
|
|
||||||
|
@ -716,8 +719,11 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
|
||||||
Hi->getLocStart(),
|
Hi->getLocStart(),
|
||||||
diag::warn_case_value_overflow);
|
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.
|
// 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();
|
Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).take();
|
||||||
CR->setRHS(Hi);
|
CR->setRHS(Hi);
|
||||||
|
|
||||||
|
|
|
@ -3743,8 +3743,16 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
||||||
// enumeration type, integral promotions (4.5) and integral
|
// enumeration type, integral promotions (4.5) and integral
|
||||||
// conversions (4.7) are applied.
|
// conversions (4.7) are applied.
|
||||||
QualType ParamType = InstantiatedParamType;
|
QualType ParamType = InstantiatedParamType;
|
||||||
QualType ArgType = Arg->getType();
|
|
||||||
if (ParamType->isIntegralOrEnumerationType()) {
|
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:
|
// C++ [temp.arg.nontype]p1:
|
||||||
// A template-argument for a non-type, non-template
|
// A template-argument for a non-type, non-template
|
||||||
// template-parameter shall be one of:
|
// template-parameter shall be one of:
|
||||||
|
@ -3868,6 +3876,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
||||||
return Owned(Arg);
|
return Owned(Arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QualType ArgType = Arg->getType();
|
||||||
DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction
|
DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction
|
||||||
|
|
||||||
// C++0x [temp.arg.nontype]p5 bullets 2, 4 and 6 permit conversion
|
// C++0x [temp.arg.nontype]p5 bullets 2, 4 and 6 permit conversion
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
|
||||||
|
|
||||||
|
template<typename T> constexpr T id(const T &t) { return t; }
|
||||||
|
|
||||||
|
struct MemberZero {
|
||||||
|
constexpr int zero() { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace TemplateArgumentConversion {
|
||||||
|
template<int n> struct IntParam {};
|
||||||
|
|
||||||
|
using IntParam0 = IntParam<0>;
|
||||||
|
// FIXME: This should be accepted once we do constexpr function invocation.
|
||||||
|
using IntParam0 = IntParam<id(0)>; // expected-error {{not an integral constant expression}}
|
||||||
|
using IntParam0 = IntParam<MemberZero().zero>; // 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче