diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-12 18:57:57 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-12 18:57:57 +0000 |
commit | 6d9ef30c5026e80fb398ed32bcdf69e4d714f033 (patch) | |
tree | 096eca5e103d89de7963dfac88c6c9719cb1e154 /lib/Sema/SemaType.cpp | |
parent | f8af98286022f72157d84951b48fde5fb369ab29 (diff) |
Implement the standard decltype() semantics described in C++11
[dcl.type.simple]p4, which treats all xvalues as returning T&&. We had
previously implemented a pre-standard variant of decltype() that
doesn't cope with, e.g., static_ast<T&&>(e) very well.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150348 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r-- | lib/Sema/SemaType.cpp | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index a235872d8f..6cc4426e5e 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -4376,8 +4376,13 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) { if (E->isTypeDependent()) return S.Context.DependentTy; - // If e is an id expression or a class member access, decltype(e) is defined - // as the type of the entity named by e. + // C++11 [dcl.type.simple]p4: + // The type denoted by decltype(e) is defined as follows: + // + // - if e is an unparenthesized id-expression or an unparenthesized class + // member access (5.2.5), decltype(e) is the type of the entity named + // by e. If there is no such entity, or if e names a set of overloaded + // functions, the program is ill-formed; if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) return VD->getType(); @@ -4386,12 +4391,7 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) { if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) return FD->getType(); } - // If e is a function call or an invocation of an overloaded operator, - // (parentheses around e are ignored), decltype(e) is defined as the - // return type of that function. - if (const CallExpr *CE = dyn_cast<CallExpr>(E->IgnoreParens())) - return CE->getCallReturnType(); - + // C++11 [expr.lambda.prim]p18: // Every occurrence of decltype((x)) where x is a possibly // parenthesized id-expression that names an entity of automatic @@ -4445,13 +4445,21 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) { } } - QualType T = E->getType(); - - // Otherwise, where T is the type of e, if e is an lvalue, decltype(e) is - // defined as T&, otherwise decltype(e) is defined as T. - if (E->isLValue()) - T = S.Context.getLValueReferenceType(T); + // 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: T = S.Context.getRValueReferenceType(T); break; + // - otherwise, if e is an lvalue, decltype(e) is T&, where T is the + // type of e; + case VK_LValue: T = S.Context.getLValueReferenceType(T); break; + // - otherwise, decltype(e) is the type of e. + case VK_RValue: break; + } + return T; } |