[Sema] Fix decltype of static data members
authorMikhail Maltsev <mikhail.maltsev@arm.com>
Wed, 14 Feb 2018 11:34:25 +0000 (11:34 +0000)
committerMikhail Maltsev <mikhail.maltsev@arm.com>
Wed, 14 Feb 2018 11:34:25 +0000 (11:34 +0000)
Summary:
According to the C++11 standard [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.

Currently Clang handles the 'member access' case incorrectly for
static data members (decltype returns T& instead of T). This patch
fixes the issue.

Reviewers: faisalv, rsmith, rogfer01

Reviewed By: rogfer01

Subscribers: rogfer01, cfe-commits

Differential Revision: https://reviews.llvm.org/D42969

llvm-svn: 325117

clang/lib/Sema/SemaType.cpp
clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp

index 8f3b359..e323b31 100644 (file)
@@ -7868,8 +7868,9 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
     if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl()))
       return VD->getType();
   } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
-    if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
-      return FD->getType();
+    if (const ValueDecl *VD = ME->getMemberDecl())
+      if (isa<FieldDecl>(VD) || isa<VarDecl>(VD))
+        return VD->getType();
   } else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(E)) {
     return IR->getDecl()->getType();
   } else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) {
index 53227ea..ee952ae 100644 (file)
@@ -12,13 +12,18 @@ struct is_same<T, T> {
 
 const int&& foo();
 int i;
-struct A { double x; };
+struct A {
+  double x;
+  static int y;
+};
 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, "");
+static_assert(is_same<decltype(a->y), int>::value, "");
+static_assert(is_same<decltype((a->y)), int&>::value, "");
 static_assert(is_same<decltype(static_cast<int&&>(i)), int&&>::value, "");
 
 int f0(int); // expected-note{{possible target}}