[PATCH] D112453: [Sema] When dereferencing a pointer of dependent type, infer the result type.

Clement Courbet via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 25 07:24:44 PDT 2021


courbet created this revision.
courbet added reviewers: rsmith, aaron.ballman.
courbet requested review of this revision.
Herald added a project: clang.

Example:

  template <typename T> auto f(T* t) {
    return *t;
  }

Before that change, the `UnaryOperator` for `*t` has type `<dependent type>`.
After the change, its type is a `T` lvalue.

I've added simple tests to verify that giving knowledge of the type to clang
does not yields false positives in contexts where c++ does not allow it to use
that knowledge.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D112453

Files:
  clang/lib/Sema/SemaOverload.cpp
  clang/test/SemaTemplate/dependent-type-identity.cpp


Index: clang/test/SemaTemplate/dependent-type-identity.cpp
===================================================================
--- clang/test/SemaTemplate/dependent-type-identity.cpp
+++ clang/test/SemaTemplate/dependent-type-identity.cpp
@@ -69,6 +69,16 @@
   void f8(typename N::X2<U>::template apply<U> *);
   void f8(typename N::X2<U>::template apply<T> *);
   void f8(typename ::Nalias::X2<type>::template apply<U_type> *); // expected-error{{redeclar}}
+
+  // (17.4.2): If an expression e is type-dependent (17.6.2.2), decltype(e)
+  // denotes a unique dependent type. Two such decltype-specifiers refer to the
+  // same type only if their expressions are equivalent (17.5.6.1)
+  T* a;
+  T* b;
+  using V = decltype(*a);
+  void f9(decltype(*a)); // expected-note{{previous}}
+  void f9(decltype(*b));
+  void f9(V); // expected-error{{redeclar}}
 };
 
 namespace PR6851 {
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -13323,10 +13323,22 @@
   ArrayRef<Expr *> ArgsArray(Args, NumArgs);
 
   if (Input->isTypeDependent()) {
-    if (Fns.empty())
-      return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy,
-                                   VK_PRValue, OK_Ordinary, OpLoc, false,
+    if (Fns.empty()) {
+      QualType ResultTy = Context.DependentTy;
+      ExprValueKind ResultKind = VK_PRValue;
+      if (getLangOpts().CPlusPlus && (Opc == UO_Deref) &&
+          Input->getType()->isPointerType()) {
+        // In c++, a deref of a `T*` always has type `T&` (16.6.8). There is no
+        // way for other overloads to be selected since overloads of `operator*`
+        // always have class or enum parameters.
+        ResultTy = cast<PointerType>(Input->getType().getCanonicalType())
+                       ->getPointeeType();
+        ResultKind = VK_LValue;
+      }
+      return UnaryOperator::Create(Context, Input, Opc, ResultTy, ResultKind,
+                                   OK_Ordinary, OpLoc, false,
                                    CurFPFeatureOverrides());
+    }
 
     CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
     ExprResult Fn = CreateUnresolvedLookupExpr(


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D112453.381987.patch
Type: text/x-patch
Size: 2286 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20211025/ce45a5b9/attachment.bin>


More information about the cfe-commits mailing list