diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1631,6 +1631,8 @@ QualType getTypeOfExprType(Expr *e) const; QualType getTypeOfType(QualType t) const; + QualType getReferenceQualifiedType(const Expr *e) const; + /// C++11 decltype. QualType getDecltypeType(Expr *e, QualType UnderlyingType) const; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2330,7 +2330,6 @@ const CXXScopeSpec &SS, QualType T, TagDecl *OwnedTagDecl = nullptr); - QualType getDecltypeForParenthesizedExpr(Expr *E); QualType BuildTypeofExprType(Expr *E, SourceLocation Loc); /// If AsUnevaluated is false, E is treated as though it were an evaluated /// context, such as when building a type for decltype(auto). diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5454,6 +5454,29 @@ return QualType(tot, 0); } +/// getReferenceQualifiedType - Given an expr, will return the type for +/// that expression, as in [dcl.type.simple]p4 but without taking id-expressions +/// and class member access into account. +QualType ASTContext::getReferenceQualifiedType(const Expr *E) const { + // C++11 [dcl.type.simple]p4: + // [...] + QualType T = E->getType(); + switch (E->getValueKind()) { + // - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the + // type of e; + case VK_XValue: + return getRValueReferenceType(T); + // - otherwise, if e is an lvalue, decltype(e) is T&, where T is the + // type of e; + case VK_LValue: + return getLValueReferenceType(T); + // - otherwise, decltype(e) is the type of e. + case VK_PRValue: + return T; + } + llvm_unreachable("Unknown value kind"); +} + /// Unlike many "get" functions, we don't unique DecltypeType /// nodes. This would never be helpful, since each such type has its own /// expression, and would not give a significant memory saving, since there diff --git a/clang/lib/AST/ExprObjC.cpp b/clang/lib/AST/ExprObjC.cpp --- a/clang/lib/AST/ExprObjC.cpp +++ b/clang/lib/AST/ExprObjC.cpp @@ -271,20 +271,7 @@ } return QT; } - - // Expression type might be different from an expected call return type, - // as expression type would never be a reference even if call returns a - // reference. Reconstruct the original expression type. - QualType QT = getType(); - switch (getValueKind()) { - case VK_LValue: - return Ctx.getLValueReferenceType(QT); - case VK_XValue: - return Ctx.getRValueReferenceType(QT); - case VK_PRValue: - return QT; - } - llvm_unreachable("Unsupported ExprValueKind"); + return Ctx.getReferenceQualifiedType(this); } SourceRange ObjCMessageExpr::getReceiverRange() const { diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -461,7 +461,7 @@ Expr *e = Req->getExpr(); S.Diag(e->getBeginLoc(), diag::note_expr_requirement_constraints_not_satisfied_simple) - << (int)First << S.getDecltypeForParenthesizedExpr(e) + << (int)First << S.Context.getReferenceQualifiedType(e) << ConstraintExpr->getNamedConcept(); } else { S.Diag(ConstraintExpr->getBeginLoc(), diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -19402,14 +19402,7 @@ if (ParamTypes.empty() && Proto->isVariadic()) { // the special case ArgTypes.reserve(E->getNumArgs()); for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { - Expr *Arg = E->getArg(i); - QualType ArgType = Arg->getType(); - if (E->isLValue()) { - ArgType = S.Context.getLValueReferenceType(ArgType); - } else if (E->isXValue()) { - ArgType = S.Context.getRValueReferenceType(ArgType); - } - ArgTypes.push_back(ArgType); + ArgTypes.push_back(S.Context.getReferenceQualifiedType(E->getArg(i))); } ParamTypes = ArgTypes; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5891,10 +5891,8 @@ // -- If E2 is an xvalue: E1 can be converted to match E2 if E1 can be // implicitly converted to the type "rvalue reference to R2", subject to // the constraint that the reference must bind directly. - if (To->isLValue() || To->isXValue()) { - QualType T = To->isLValue() ? Self.Context.getLValueReferenceType(ToType) - : Self.Context.getRValueReferenceType(ToType); - + if (To->isGLValue()) { + QualType T = Self.Context.getReferenceQualifiedType(To); InitializedEntity Entity = InitializedEntity::InitializeTemporary(T); InitializationSequence InitSeq(Self, Entity, Kind, From); @@ -8743,7 +8741,7 @@ TemplateParameterList *TPL = ReturnTypeRequirement.getTypeConstraintTemplateParameterList(); QualType MatchedType = - getDecltypeForParenthesizedExpr(E).getCanonicalType(); + Context.getReferenceQualifiedType(E).getCanonicalType(); llvm::SmallVector Args; Args.push_back(TemplateArgument(MatchedType)); TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -8891,29 +8891,6 @@ return Context.getTypeOfExprType(E); } -/// getDecltypeForParenthesizedExpr - Given an expr, will return the type for -/// that expression, as in [dcl.type.simple]p4 but without taking id-expressions -/// and class member access into account. -QualType Sema::getDecltypeForParenthesizedExpr(Expr *E) { - // C++11 [dcl.type.simple]p4: - // [...] - QualType T = E->getType(); - switch (E->getValueKind()) { - // - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the - // type of e; - case VK_XValue: - return Context.getRValueReferenceType(T); - // - otherwise, if e is an lvalue, decltype(e) is T&, where T is the - // type of e; - case VK_LValue: - return Context.getLValueReferenceType(T); - // - otherwise, decltype(e) is the type of e. - case VK_PRValue: - return T; - } - llvm_unreachable("Unknown value kind"); -} - /// getDecltypeForExpr - Given an expr, will return the decltype for /// that expression, according to the rules in C++11 /// [dcl.type.simple]p4 and C++11 [expr.lambda.prim]p18. @@ -8983,7 +8960,7 @@ } } - return S.getDecltypeForParenthesizedExpr(E); + return S.Context.getReferenceQualifiedType(E); } QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc, diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp --- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -73,26 +73,7 @@ const Expr *E = getOriginExpr(); if (!E) return Ctx.VoidTy; - assert(E); - - QualType ResultTy = E->getType(); - - // A function that returns a reference to 'int' will have a result type - // of simply 'int'. Check the origin expr's value kind to recover the - // proper type. - switch (E->getValueKind()) { - case VK_LValue: - ResultTy = Ctx.getLValueReferenceType(ResultTy); - break; - case VK_XValue: - ResultTy = Ctx.getRValueReferenceType(ResultTy); - break; - case VK_PRValue: - // No adjustment is necessary. - break; - } - - return ResultTy; + return Ctx.getReferenceQualifiedType(E); } static bool isCallback(QualType T) {