Commit a29aa471 authored by Anastasia Stulova's avatar Anastasia Stulova
Browse files

[OpenCL] Move addr space deduction to Sema.

In order to simplify implementation we are moving add space
deduction into Sema while constructing variable declaration
and on template instantiation. Pointee are deduced to generic
addr space during creation of types.

This commit also
- fixed addr space dedution for auto type;
- factors out in a separate helper function OpenCL specific
  logic from type diagnostics in var decl.

Tags: #clang

Differential Revision: https://reviews.llvm.org/D65744
parent 3edf2eb8
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -2069,6 +2069,8 @@ public:
  bool isAlignValT() const;                     // C++17 std::align_val_t
  bool isStdByteType() const;                   // C++17 std::byte
  bool isAtomicType() const;                    // C11 _Atomic()
  bool isUndeducedAutoType() const;             // C++11 auto or
                                                // C++14 decltype(auto)

#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
  bool is##Id##Type() const;
@@ -6509,6 +6511,10 @@ inline bool Type::isAtomicType() const {
  return isa<AtomicType>(CanonicalType);
}

inline bool Type::isUndeducedAutoType() const {
  return isa<AutoType>(CanonicalType);
}

inline bool Type::isObjCQualifiedIdType() const {
  if (const auto *OPT = getAs<ObjCObjectPointerType>())
    return OPT->isObjCQualifiedIdType();
+2 −0
Original line number Diff line number Diff line
@@ -8760,6 +8760,8 @@ public:
  bool CheckARCMethodDecl(ObjCMethodDecl *method);
  bool inferObjCARCLifetime(ValueDecl *decl);
  void deduceOpenCLAddressSpace(ValueDecl *decl);
  ExprResult
  HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
                            Expr *BaseExpr,
+1 −1
Original line number Diff line number Diff line
@@ -1814,7 +1814,7 @@ bool CastExpr::CastConsistency() const {
    auto Ty = getType();
    auto SETy = getSubExpr()->getType();
    assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy));
    if (/*isRValue()*/ !Ty->getPointeeType().isNull()) {
    if (isRValue()) {
      Ty = Ty->getPointeeType();
      SETy = SETy->getPointeeType();
    }
+129 −89
Original line number Diff line number Diff line
@@ -6117,6 +6117,22 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
  return false;
}
void Sema::deduceOpenCLAddressSpace(ValueDecl *Decl) {
  if (Decl->getType().getQualifiers().hasAddressSpace())
    return;
  if (VarDecl *Var = dyn_cast<VarDecl>(Decl)) {
    QualType Type = Var->getType();
    if (Type->isSamplerT() || Type->isVoidType())
      return;
    LangAS ImplAS = LangAS::opencl_private;
    if ((getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) &&
        Var->hasGlobalStorage())
      ImplAS = LangAS::opencl_global;
    Type = Context.getAddrSpaceQualType(Type, ImplAS);
    Decl->setType(Type);
  }
}
static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
  // Ensure that an auto decl is deduced otherwise the checks below might cache
  // the wrong linkage.
@@ -6474,51 +6490,32 @@ static bool isDeclExternC(const Decl *D) {
  llvm_unreachable("Unknown type of decl!");
}
NamedDecl *Sema::ActOnVariableDeclarator(
    Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo,
    LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists,
    bool &AddToScope, ArrayRef<BindingDecl *> Bindings) {
  QualType R = TInfo->getType();
  DeclarationName Name = GetNameForDeclarator(D).getName();
  IdentifierInfo *II = Name.getAsIdentifierInfo();
  if (D.isDecompositionDeclarator()) {
    // Take the name of the first declarator as our name for diagnostic
    // purposes.
    auto &Decomp = D.getDecompositionDeclarator();
    if (!Decomp.bindings().empty()) {
      II = Decomp.bindings()[0].Name;
      Name = II;
    }
  } else if (!II) {
    Diag(D.getIdentifierLoc(), diag::err_bad_variable_name) << Name;
    return nullptr;
  }
  if (getLangOpts().OpenCL) {
/// Returns true if there hasn't been any invalid type diagnosed.
static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D,
                                DeclContext *DC, QualType R) {
  // OpenCL v2.0 s6.9.b - Image type can only be used as a function argument.
  // OpenCL v2.0 s6.13.16.1 - Pipe type can only be used as a function
  // argument.
  if (R->isImageType() || R->isPipeType()) {
      Diag(D.getIdentifierLoc(),
    Se.Diag(D.getIdentifierLoc(),
            diag::err_opencl_type_can_only_be_used_as_function_parameter)
        << R;
    D.setInvalidType();
      return nullptr;
    return false;
  }
  // OpenCL v1.2 s6.9.r:
  // The event type cannot be used to declare a program scope variable.
  // OpenCL v2.0 s6.9.q:
    // The clk_event_t and reserve_id_t types cannot be declared in program scope.
  // The clk_event_t and reserve_id_t types cannot be declared in program
  // scope.
  if (NULL == S->getParent()) {
    if (R->isReserveIDT() || R->isClkEventT() || R->isEventT()) {
        Diag(D.getIdentifierLoc(),
             diag::err_invalid_type_for_program_scope_var) << R;
      Se.Diag(D.getIdentifierLoc(),
              diag::err_invalid_type_for_program_scope_var)
          << R;
      D.setInvalidType();
        return nullptr;
      return false;
    }
  }
@@ -6526,20 +6523,46 @@ NamedDecl *Sema::ActOnVariableDeclarator(
  QualType NR = R;
  while (NR->isPointerType()) {
    if (NR->isFunctionPointerType()) {
        Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer);
      Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer);
      D.setInvalidType();
        break;
      return false;
    }
    NR = NR->getPointeeType();
  }
    if (!getOpenCLOptions().isEnabled("cl_khr_fp16")) {
  if (!Se.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
    // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
    // half array type (unless the cl_khr_fp16 extension is enabled).
      if (Context.getBaseElementType(R)->isHalfType()) {
        Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R;
    if (Se.Context.getBaseElementType(R)->isHalfType()) {
      Se.Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R;
      D.setInvalidType();
      return false;
    }
  }
  // OpenCL v1.2 s6.9.r:
  // The event type cannot be used with the __local, __constant and __global
  // address space qualifiers.
  if (R->isEventT()) {
    if (R.getAddressSpace() != LangAS::opencl_private) {
      Se.Diag(D.getBeginLoc(), diag::err_event_t_addr_space_qual);
      D.setInvalidType();
      return false;
    }
  }
  // C++ for OpenCL does not allow the thread_local storage qualifier.
  // OpenCL C does not support thread_local either, and
  // also reject all other thread storage class specifiers.
  DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec();
  if (TSC != TSCS_unspecified) {
    bool IsCXX = Se.getLangOpts().OpenCLCPlusPlus;
    Se.Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
            diag::err_opencl_unknown_type_specifier)
        << IsCXX << Se.getLangOpts().getOpenCLVersionTuple().getAsString()
        << DeclSpec::getSpecifierName(TSC) << 1;
    D.setInvalidType();
    return false;
  }
  if (R->isSamplerT()) {
@@ -6548,7 +6571,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
    // space qualifiers.
    if (R.getAddressSpace() == LangAS::opencl_local ||
        R.getAddressSpace() == LangAS::opencl_global) {
        Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
      Se.Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
      D.setInvalidType();
    }
    // OpenCL v1.2 s6.12.14.1:
@@ -6557,36 +6581,38 @@ NamedDecl *Sema::ActOnVariableDeclarator(
    if (DC->isTranslationUnit() &&
        !(R.getAddressSpace() == LangAS::opencl_constant ||
          R.isConstQualified())) {
        Diag(D.getIdentifierLoc(), diag::err_opencl_nonconst_global_sampler);
      Se.Diag(D.getIdentifierLoc(), diag::err_opencl_nonconst_global_sampler);
      D.setInvalidType();
    }
    if (D.isInvalidType())
      return false;
  }
    // OpenCL v1.2 s6.9.r:
    // The event type cannot be used with the __local, __constant and __global
    // address space qualifiers.
    if (R->isEventT()) {
      if (R.getAddressSpace() != LangAS::opencl_private) {
        Diag(D.getBeginLoc(), diag::err_event_t_addr_space_qual);
        D.setInvalidType();
      }
  return true;
}
    // C++ for OpenCL does not allow the thread_local storage qualifier.
    // OpenCL C does not support thread_local either, and
    // also reject all other thread storage class specifiers.
    DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec();
    if (TSC != TSCS_unspecified) {
      bool IsCXX = getLangOpts().OpenCLCPlusPlus;
      Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
           diag::err_opencl_unknown_type_specifier)
          << IsCXX << getLangOpts().getOpenCLVersionTuple().getAsString()
          << DeclSpec::getSpecifierName(TSC) << 1;
      D.setInvalidType();
      return nullptr;
NamedDecl *Sema::ActOnVariableDeclarator(
    Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo,
    LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists,
    bool &AddToScope, ArrayRef<BindingDecl *> Bindings) {
  QualType R = TInfo->getType();
  DeclarationName Name = GetNameForDeclarator(D).getName();
  IdentifierInfo *II = Name.getAsIdentifierInfo();
  if (D.isDecompositionDeclarator()) {
    // Take the name of the first declarator as our name for diagnostic
    // purposes.
    auto &Decomp = D.getDecompositionDeclarator();
    if (!Decomp.bindings().empty()) {
      II = Decomp.bindings()[0].Name;
      Name = II;
    }
  } else if (!II) {
    Diag(D.getIdentifierLoc(), diag::err_bad_variable_name) << Name;
    return nullptr;
  }
  DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
  StorageClass SC = StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
@@ -6942,6 +6968,13 @@ NamedDecl *Sema::ActOnVariableDeclarator(
    }
  }
  if (getLangOpts().OpenCL) {
    deduceOpenCLAddressSpace(NewVD);
    diagnoseOpenCLTypes(S, *this, D, DC, NewVD->getType());
  }
  // Handle attributes prior to checking for duplicates in MergeVarDecl
  ProcessDeclAttributes(S, NewVD, D);
@@ -11285,6 +11318,9 @@ bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit,
  if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl))
    VDecl->setInvalidDecl();
  if (getLangOpts().OpenCL)
    deduceOpenCLAddressSpace(VDecl);
  // If this is a redeclaration, check that the type we just deduced matches
  // the previously declared type.
  if (VarDecl *Old = VDecl->getPreviousDecl()) {
@@ -13107,6 +13143,10 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
  if (New->hasAttr<BlocksAttr>()) {
    Diag(New->getLocation(), diag::err_block_on_nonlocal);
  }
  if (getLangOpts().OpenCL)
    deduceOpenCLAddressSpace(New);
  return New;
}
+6 −2
Original line number Diff line number Diff line
@@ -1514,8 +1514,12 @@ TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
                                                 int indexAdjustment,
                                               Optional<unsigned> NumExpansions,
                                                 bool ExpectParameterPack) {
  return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment,
  auto NewParm =
      SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment,
                               NumExpansions, ExpectParameterPack);
  if (NewParm && SemaRef.getLangOpts().OpenCL)
    SemaRef.deduceOpenCLAddressSpace(NewParm);
  return NewParm;
}

QualType
Loading