chrisbazley created this revision.
Herald added a project: All.
chrisbazley requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The semantics of the unary & operator are modified
so that if its  operand has type "type" then its
result has type "pointer to type", with the omission
of any _Optional qualifier of the pointed-to type.

Also added a new helper method,
ASTContext::getNonOptionalType.

Rationale:

A new idiom &* is proposed to allow removal of the
_Optional qualifier from a pointee whilst allowing
static analyzers to check the validity of such
conversions. This is merely the simplest expression
that incorporates a semantic dereference without
actually accessing the pointed-to object.

There is only one way to get the address of an object
(excepting arithmetic), whereas there are many ways
to dereference a pointer. This is why the semantics
of & are modified rather than modifying *, [] and ->.
The operand of  & is already treated specially, being
exempt from implicit conversion of an array type into
a pointer, for example.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142734

Files:
  clang/include/clang/AST/ASTContext.h
  clang/lib/Sema/SemaExpr.cpp

Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -14585,10 +14585,18 @@
   if (getLangOpts().C99) {
     // Implement C99-only parts of addressof rules.
     if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
-      if (uOp->getOpcode() == UO_Deref)
+      if (uOp->getOpcode() == UO_Deref) {
         // Per C99 6.5.3.2, the address of a deref always returns a valid result
         // (assuming the deref expression is valid).
-        return uOp->getSubExpr()->getType();
+        auto Result = uOp->getSubExpr()->getType();
+        if (const PointerType *PT = Result->getAs<PointerType>()) {
+          // A dereferenced pointer is not a null pointer (by definition).
+          auto PointeeType = PT->getPointeeType();
+          Result =
+              Context.getPointerType(Context.getNonOptionalType(PointeeType));
+        }
+        return Result;
+      }
     }
     // Technically, there should be a check for array subscript
     // expressions here, but the result of one is always an lvalue anyway.
@@ -14602,6 +14610,7 @@
 
   Expr::LValueClassification lval = op->ClassifyLValue(Context);
   unsigned AddressOfError = AO_No_Error;
+  QualType Ty = Context.getNonOptionalType(op->getType());
 
   if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) {
     bool sfinae = (bool)isSFINAEContext();
@@ -14611,10 +14620,9 @@
     if (sfinae)
       return QualType();
     // Materialize the temporary as an lvalue so that we can take its address.
-    OrigOp = op =
-        CreateMaterializeTemporaryExpr(op->getType(), OrigOp.get(), true);
+    OrigOp = op = CreateMaterializeTemporaryExpr(Ty, OrigOp.get(), true);
   } else if (isa<ObjCSelectorExpr>(op)) {
-    return Context.getPointerType(op->getType());
+    return Context.getPointerType(Ty);
   } else if (lval == Expr::LV_MemberFunction) {
     // If it's an instance method, make a member pointer.
     // The expression must have exactly the form &A::foo.
@@ -14652,7 +14660,7 @@
       Diag(OpLoc, diag::err_typecheck_addrof_dtor) << op->getSourceRange();
 
     QualType MPTy = Context.getMemberPointerType(
-        op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr());
+        Ty, Context.getTypeDeclType(MD->getParent()).getTypePtr());
     // Under the MS ABI, lock down the inheritance model now.
     if (Context.getTargetInfo().getCXXABI().isMicrosoft())
       (void)isCompleteType(OpLoc, MPTy);
@@ -14660,7 +14668,7 @@
   } else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
     // C99 6.5.3.2p1
     // The operand must be either an l-value or a function designator
-    if (!op->getType()->isFunctionType()) {
+    if (!Ty->isFunctionType()) {
       // Use a special diagnostic for loads from property references.
       if (isa<PseudoObjectExpr>(op)) {
         AddressOfError = AO_Property_Expansion;
@@ -14711,8 +14719,7 @@
             Ctx = Ctx->getParent();
 
           QualType MPTy = Context.getMemberPointerType(
-              op->getType(),
-              Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+              Ty, Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
           // Under the MS ABI, lock down the inheritance model now.
           if (Context.getTargetInfo().getCXXABI().isMicrosoft())
             (void)isCompleteType(OpLoc, MPTy);
@@ -14737,12 +14744,12 @@
   }
 
   // If the operand has type "type", the result has type "pointer to type".
-  if (op->getType()->isObjCObjectType())
-    return Context.getObjCObjectPointerType(op->getType());
+  if (Ty->isObjCObjectType())
+    return Context.getObjCObjectPointerType(Ty);
 
   CheckAddressOfPackedMember(op);
 
-  return Context.getPointerType(op->getType());
+  return Context.getPointerType(Ty);
 }
 
 static void RecordModifiableNonNullParam(Sema &S, const Expr *Exp) {
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -2151,6 +2151,18 @@
     return getQualifiedType(type.getUnqualifiedType(), Qs);
   }
 
+  /// Return a type without the optional qualifier.
+  QualType getNonOptionalType(QualType type) const {
+    if (type.isLocalOptionalQualified()) {
+      type.removeLocalOptional();
+    } else if (type.isOptionalQualified()) {
+      Qualifiers Qs = type.getQualifiers();
+      Qs.removeOptional();
+      type = getQualifiedType(type.getUnqualifiedType(), Qs);
+    }
+    return type;
+  }
+
   unsigned char getFixedPointScale(QualType Ty) const;
   unsigned char getFixedPointIBits(QualType Ty) const;
   llvm::FixedPointSemantics getFixedPointSemantics(QualType Ty) const;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D142734: Update... Christopher Bazley via Phabricator via cfe-commits

Reply via email to