diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 107 |
3 files changed, 87 insertions, 56 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 2ebf757ffa..bbead42f03 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/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/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7b706cb262..17920d00e6 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/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/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 538bb6aafd..93b42829bb 100644 --- a/lib/Sema/SemaType.cpp +++ b/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; |