diff options
| author | Anastasia Stulova <anastasia.stulova@arm.com> | 2019-01-21 16:01:38 +0000 |
|---|---|---|
| committer | Anastasia Stulova <anastasia.stulova@arm.com> | 2019-01-21 16:01:38 +0000 |
| commit | 5cffa454011498450c30bf8d29c5a024996871c4 (patch) | |
| tree | 61e4c169bebd128fd9fe78853474ea6a641aad96 /clang/lib | |
| parent | cfa434ae411b0ff04a05fcd1e850cfbf872644cb (diff) | |
| download | bcm5719-llvm-5cffa454011498450c30bf8d29c5a024996871c4.tar.gz bcm5719-llvm-5cffa454011498450c30bf8d29c5a024996871c4.zip | |
[OpenCL] Allow address spaces as method qualifiers.
Methods can now be qualified with address spaces to prevent
undesirable conversions to generic or to provide custom
implementation to be used if the object is located in certain
memory segments.
This commit extends parsing and standard C++ overloading to
work for an address space of a method (i.e. implicit 'this'
parameter).
Differential Revision: https://reviews.llvm.org/D55850
llvm-svn: 351747
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 14 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 22 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaType.cpp | 107 |
3 files changed, 87 insertions, 56 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 2ebf757ffa2..bbead42f031 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6177,6 +6177,20 @@ void Parser::ParseFunctionDeclarator(Declarator &D, Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers()); if (D.getDeclSpec().isConstexprSpecified() && !getLangOpts().CPlusPlus14) Q.addConst(); + // FIXME: Collect C++ address spaces. + // If there are multiple different address spaces, the source is invalid. + // Carry on using the first addr space for the qualifiers of 'this'. + // The diagnostic will be given later while creating the function + // prototype for the method. + if (getLangOpts().OpenCLCPlusPlus) { + for (ParsedAttr &attr : DS.getAttributes()) { + LangAS ASIdx = attr.asOpenCLLangAS(); + if (ASIdx != LangAS::Default) { + Q.addAddressSpace(ASIdx); + break; + } + } + } Sema::CXXThisScopeRAII ThisScope( Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), Q, diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 7b706cb2625..17920d00e6f 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1171,16 +1171,14 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, // function yet (because we haven't yet resolved whether this is a static // or non-static member function). Add it now, on the assumption that this // is a redeclaration of OldMethod. - // FIXME: OpenCL: Need to consider address spaces - unsigned OldQuals = OldMethod->getTypeQualifiers().getCVRUQualifiers(); - unsigned NewQuals = NewMethod->getTypeQualifiers().getCVRUQualifiers(); + auto OldQuals = OldMethod->getTypeQualifiers(); + auto NewQuals = NewMethod->getTypeQualifiers(); if (!getLangOpts().CPlusPlus14 && NewMethod->isConstexpr() && !isa<CXXConstructorDecl>(NewMethod)) - NewQuals |= Qualifiers::Const; - + NewQuals.addConst(); // We do not allow overloading based off of '__restrict'. - OldQuals &= ~Qualifiers::Restrict; - NewQuals &= ~Qualifiers::Restrict; + OldQuals.removeRestrict(); + NewQuals.removeRestrict(); if (OldQuals != NewQuals) return true; } @@ -5150,6 +5148,16 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType, return ICS; } + if (FromTypeCanon.getQualifiers().hasAddressSpace()) { + Qualifiers QualsImplicitParamType = ImplicitParamType.getQualifiers(); + Qualifiers QualsFromType = FromTypeCanon.getQualifiers(); + if (!QualsImplicitParamType.isAddressSpaceSupersetOf(QualsFromType)) { + ICS.setBad(BadConversionSequence::bad_qualifiers, + FromType, ImplicitParamType); + return ICS; + } + } + // Check that we have either the same type or a derived type. It // affects the conversion rank. QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 538bb6aafd0..93b42829bba 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3915,6 +3915,25 @@ static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr, llvm_unreachable("unknown NullabilityKind"); } +// Diagnose whether this is a case with the multiple addr spaces. +// Returns true if this is an invalid case. +// ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified +// by qualifiers for two or more different address spaces." +static bool DiagnoseMultipleAddrSpaceAttributes(Sema &S, LangAS ASOld, + LangAS ASNew, + SourceLocation AttrLoc) { + if (ASOld != LangAS::Default) { + if (ASOld != ASNew) { + S.Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers); + return true; + } + // Emit a warning if they are identical; it's likely unintended. + S.Diag(AttrLoc, + diag::warn_attribute_address_multiple_identical_qualifiers); + } + return false; +} + static TypeSourceInfo * GetTypeSourceInfoForDeclarator(TypeProcessingState &State, QualType T, TypeSourceInfo *ReturnTypeInfo); @@ -4822,18 +4841,35 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, Exceptions, EPI.ExceptionSpec); - const auto &Spec = D.getCXXScopeSpec(); + // FIXME: Set address space from attrs for C++ mode here. // OpenCLCPlusPlus: A class member function has an address space. - if (state.getSema().getLangOpts().OpenCLCPlusPlus && - ((!Spec.isEmpty() && - Spec.getScopeRep()->getKind() == NestedNameSpecifier::TypeSpec) || - state.getDeclarator().getContext() == - DeclaratorContext::MemberContext)) { - LangAS CurAS = EPI.TypeQuals.getAddressSpace(); + auto IsClassMember = [&]() { + return (!state.getDeclarator().getCXXScopeSpec().isEmpty() && + state.getDeclarator() + .getCXXScopeSpec() + .getScopeRep() + ->getKind() == NestedNameSpecifier::TypeSpec) || + state.getDeclarator().getContext() == + DeclaratorContext::MemberContext; + }; + + if (state.getSema().getLangOpts().OpenCLCPlusPlus && IsClassMember()) { + LangAS ASIdx = LangAS::Default; + // Take address space attr if any and mark as invalid to avoid adding + // them later while creating QualType. + if (FTI.MethodQualifiers) + for (ParsedAttr &attr : FTI.MethodQualifiers->getAttributes()) { + LangAS ASIdxNew = attr.asOpenCLLangAS(); + if (DiagnoseMultipleAddrSpaceAttributes(S, ASIdx, ASIdxNew, + attr.getLoc())) + D.setInvalidType(true); + else + ASIdx = ASIdxNew; + } // If a class member function's address space is not set, set it to // __generic. LangAS AS = - (CurAS == LangAS::Default ? LangAS::opencl_generic : CurAS); + (ASIdx == LangAS::Default ? LangAS::opencl_generic : ASIdx); EPI.TypeQuals.addAddressSpace(AS); } T = Context.getFunctionType(T, ParamTys, EPI); @@ -5789,19 +5825,9 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, LangAS ASIdx = getLangASFromTargetAS(static_cast<unsigned>(addrSpace.getZExtValue())); - // If this type is already address space qualified with a different - // address space, reject it. - // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified - // by qualifiers for two or more different address spaces." - if (T.getAddressSpace() != LangAS::Default) { - if (T.getAddressSpace() != ASIdx) { - Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers); - return QualType(); - } else - // Emit a warning if they are identical; it's likely unintended. - Diag(AttrLoc, - diag::warn_attribute_address_multiple_identical_qualifiers); - } + if (DiagnoseMultipleAddrSpaceAttributes(*this, T.getAddressSpace(), ASIdx, + AttrLoc)) + return QualType(); return Context.getAddrSpaceQualType(T, ASIdx); } @@ -5879,34 +5905,14 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, } } else { // The keyword-based type attributes imply which address space to use. - switch (Attr.getKind()) { - case ParsedAttr::AT_OpenCLGlobalAddressSpace: - ASIdx = LangAS::opencl_global; break; - case ParsedAttr::AT_OpenCLLocalAddressSpace: - ASIdx = LangAS::opencl_local; break; - case ParsedAttr::AT_OpenCLConstantAddressSpace: - ASIdx = LangAS::opencl_constant; break; - case ParsedAttr::AT_OpenCLGenericAddressSpace: - ASIdx = LangAS::opencl_generic; break; - case ParsedAttr::AT_OpenCLPrivateAddressSpace: - ASIdx = LangAS::opencl_private; break; - default: + ASIdx = Attr.asOpenCLLangAS(); + if (ASIdx == LangAS::Default) llvm_unreachable("Invalid address space"); - } - // If this type is already address space qualified with a different - // address space, reject it. - // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified by - // qualifiers for two or more different address spaces." - if (Type.getAddressSpace() != LangAS::Default) { - if (Type.getAddressSpace() != ASIdx) { - S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers); - Attr.setInvalid(); - return; - } else - // Emit a warning if they are identical; it's likely unintended. - S.Diag(Attr.getLoc(), - diag::warn_attribute_address_multiple_identical_qualifiers); + if (DiagnoseMultipleAddrSpaceAttributes(S, Type.getAddressSpace(), ASIdx, + Attr.getLoc())) { + Attr.setInvalid(); + return; } Type = S.Context.getAddrSpaceQualType(Type, ASIdx); @@ -7243,9 +7249,12 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, // Do not deduce addr space of the void type, e.g. in f(void), otherwise // it will fail some sema check. (T->isVoidType() && !IsPointee) || - // Do not deduce address spaces for dependent types because they might end + // Do not deduce addr spaces for dependent types because they might end // up instantiating to a type with an explicit address space qualifier. - T->isDependentType()) + T->isDependentType() || + // Do not deduce addr space of decltype because it will be taken from + // its argument. + T->isDecltypeType()) return; LangAS ImpAddr = LangAS::Default; |

