diff options
-rw-r--r-- | lib/AST/ASTContext.cpp | 34 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 5 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp | 21 |
3 files changed, 53 insertions, 7 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index e23bb34b05..377d2fbe9a 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1663,15 +1663,43 @@ QualType ASTContext::getTypeOfType(QualType tofType) { return QualType(tot, 0); } +/// getDecltypeForExpr - Given an expr, will return the decltype for that +/// expression, according to the rules in C++0x [dcl.type.simple]p4 +static QualType getDecltypeForExpr(const Expr *e, ASTContext &Context) { + // If e is an id expression or a class member access, decltype(e) is defined + // as the type of the entity named by e. + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(e)) { + if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) + return VD->getType(); + } + if (const MemberExpr *ME = dyn_cast<MemberExpr>(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(); + + 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(Context) == Expr::LV_Valid) + T = Context.getLValueReferenceType(T); + + return T; +} + /// getDecltypeType - Unlike many "get<Type>" functions, we don't unique /// DecltypeType AST's. The only motivation to unique these nodes would be /// memory savings. Since decltype(t) is fairly uncommon, space shouldn't be /// an issue. This doesn't effect the type checker, since it operates /// on canonical type's (which are always unique). QualType ASTContext::getDecltypeType(Expr *e) { - // FIXME: Use the right type here! - QualType Canonical = getCanonicalType(e->getType()); - DecltypeType *dt = new (*this, 8) DecltypeType(e, Canonical); + QualType T = getDecltypeForExpr(e, *this); + DecltypeType *dt = new (*this, 8) DecltypeType(e, getCanonicalType(T)); Types.push_back(dt); return QualType(dt, 0); } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 297dee9a50..12077b0671 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -240,10 +240,7 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, Expr *E = static_cast<Expr *>(DS.getTypeRep()); assert(E && "Didn't get an expression for decltype?"); // TypeQuals handled by caller. - - // FIXME: Use the right type! - Result = Context.IntTy; - isInvalid = true; + Result = Context.getDecltypeType(E); break; } diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp new file mode 100644 index 0000000000..d97f2b83d1 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp @@ -0,0 +1,21 @@ +// RUN: clang-cc -fsyntax-only -std=c++0x -verify %s + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +const int&& foo(); +int i; +struct A { double x; }; +const A* a = new A(); + +static_assert(is_same<decltype(foo()), const int&&>::value, ""); +static_assert(is_same<decltype(i), int>::value, ""); +static_assert(is_same<decltype(a->x), double>::value, ""); +static_assert(is_same<decltype((a->x)), const double&>::value, ""); |