]> granicus.if.org Git - clang/commitdiff
[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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@325117 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 8f3b359fde18e7f973cc3d6adef8e4d29bfa6f95..e323b31f8e7539fe7409afceeac2760d15ff3f25 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 53227ea37ce9e92eb4482d813e91be984f4f8d98..ee952aeaf0c929e11d39577de3e53198a1c8cbb4 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}}