From 90646732bf1366f9df93fd41a58323cb8f8e0fce Mon Sep 17 00:00:00 2001 From: Mikael Nilsson Date: Wed, 12 Dec 2018 15:06:16 +0000 Subject: [PATCH] Revert "[OpenCL] Add generic AS to 'this' pointer" Reverting because the patch broke lldb. llvm-svn: 348931 --- clang/include/clang/AST/CanonicalType.h | 2 +- clang/include/clang/AST/DeclCXX.h | 5 +- clang/include/clang/AST/Type.h | 54 +++----- clang/include/clang/Sema/Sema.h | 4 +- clang/lib/AST/ASTContext.cpp | 5 +- clang/lib/AST/ASTDumper.cpp | 7 +- clang/lib/AST/DeclCXX.cpp | 15 +- clang/lib/AST/ItaniumMangle.cpp | 5 +- clang/lib/AST/MicrosoftMangle.cpp | 2 +- clang/lib/AST/Type.cpp | 16 +-- clang/lib/AST/TypePrinter.cpp | 6 +- clang/lib/CodeGen/CGCall.cpp | 16 +-- clang/lib/CodeGen/CGClass.cpp | 14 +- clang/lib/CodeGen/CGDebugInfo.cpp | 6 +- clang/lib/CodeGen/CGDeclCXX.cpp | 5 +- clang/lib/CodeGen/CGExpr.cpp | 2 +- clang/lib/CodeGen/CGValue.h | 5 +- clang/lib/Index/USRGeneration.cpp | 3 +- clang/lib/Parse/ParseCXXInlineMethods.cpp | 2 +- clang/lib/Parse/ParseDecl.cpp | 17 ++- clang/lib/Parse/ParseOpenMP.cpp | 2 +- clang/lib/Sema/SemaCodeComplete.cpp | 12 +- clang/lib/Sema/SemaDecl.cpp | 11 +- clang/lib/Sema/SemaDeclCXX.cpp | 8 +- clang/lib/Sema/SemaExpr.cpp | 4 +- clang/lib/Sema/SemaExprCXX.cpp | 11 +- clang/lib/Sema/SemaLambda.cpp | 10 +- clang/lib/Sema/SemaOverload.cpp | 35 ++--- clang/lib/Sema/SemaTemplate.cpp | 2 +- clang/lib/Sema/SemaTemplateDeduction.cpp | 5 +- clang/lib/Sema/SemaTemplateInstantiate.cpp | 10 +- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 10 +- clang/lib/Sema/SemaType.cpp | 30 +--- clang/lib/Sema/TreeTransform.h | 13 +- clang/lib/Serialization/ASTReader.cpp | 2 +- clang/lib/Serialization/ASTWriter.cpp | 2 +- clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl | 154 --------------------- .../CodeGenOpenCLCXX/template-address-spaces.cl | 15 +- .../test/SemaOpenCLCXX/address-space-templates.cl | 4 +- clang/tools/libclang/CIndex.cpp | 2 +- 40 files changed, 143 insertions(+), 390 deletions(-) delete mode 100644 clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h index c2f01e7..0e738da 100644 --- a/clang/include/clang/AST/CanonicalType.h +++ b/clang/include/clang/AST/CanonicalType.h @@ -510,7 +510,7 @@ struct CanProxyAdaptor } LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getTypeQuals) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals) using param_type_iterator = CanTypeIterator; diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 58e01bf..9b80d50 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2182,10 +2182,7 @@ public: /// 'this' type. QualType getThisType(ASTContext &C) const; - static QualType getThisType(const FunctionProtoType *FPT, - const CXXRecordDecl *Decl); - - Qualifiers getTypeQualifiers() const { + unsigned getTypeQualifiers() const { return getType()->getAs()->getTypeQuals(); } diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 5b69570..4a9decf 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -256,24 +256,28 @@ public: } bool hasConst() const { return Mask & Const; } - bool hasOnlyConst() const { return Mask == Const; } + void setConst(bool flag) { + Mask = (Mask & ~Const) | (flag ? Const : 0); + } void removeConst() { Mask &= ~Const; } void addConst() { Mask |= Const; } bool hasVolatile() const { return Mask & Volatile; } - bool hasOnlyVolatile() const { return Mask == Volatile; } + void setVolatile(bool flag) { + Mask = (Mask & ~Volatile) | (flag ? Volatile : 0); + } void removeVolatile() { Mask &= ~Volatile; } void addVolatile() { Mask |= Volatile; } bool hasRestrict() const { return Mask & Restrict; } - bool hasOnlyRestrict() const { return Mask == Restrict; } + void setRestrict(bool flag) { + Mask = (Mask & ~Restrict) | (flag ? Restrict : 0); + } void removeRestrict() { Mask &= ~Restrict; } void addRestrict() { Mask |= Restrict; } bool hasCVRQualifiers() const { return getCVRQualifiers(); } unsigned getCVRQualifiers() const { return Mask & CVRMask; } - unsigned getCVRUQualifiers() const { return Mask & (CVRMask | UMask); } - void setCVRQualifiers(unsigned mask) { assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); Mask = (Mask & ~CVRMask) | mask; @@ -1522,9 +1526,7 @@ protected: /// /// C++ 8.3.5p4: The return type, the parameter type list and the /// cv-qualifier-seq, [...], are part of the function type. - unsigned FastTypeQuals : Qualifiers::FastWidth; - /// Whether this function has extended Qualifiers. - unsigned HasExtQuals : 1; + unsigned TypeQuals : 4; /// The number of parameters this function has, not counting '...'. /// According to [implimits] 8 bits should be enough here but this is @@ -3609,9 +3611,7 @@ protected: FunctionTypeBits.ExtInfo = Info.Bits; } - Qualifiers getFastTypeQuals() const { - return Qualifiers::fromFastMask(FunctionTypeBits.FastTypeQuals); - } + unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; } public: QualType getReturnType() const { return ResultType; } @@ -3626,14 +3626,9 @@ public: CallingConv getCallConv() const { return getExtInfo().getCC(); } ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); } - - static_assert((~Qualifiers::FastMask & Qualifiers::CVRMask) == 0, - "Const, volatile and restrict are assumed to be a subset of " - "the fast qualifiers."); - - bool isConst() const { return getFastTypeQuals().hasConst(); } - bool isVolatile() const { return getFastTypeQuals().hasVolatile(); } - bool isRestrict() const { return getFastTypeQuals().hasRestrict(); } + bool isConst() const { return getTypeQuals() & Qualifiers::Const; } + bool isVolatile() const { return getTypeQuals() & Qualifiers::Volatile; } + bool isRestrict() const { return getTypeQuals() & Qualifiers::Restrict; } /// Determine the type of an expression that calls a function of /// this type. @@ -3694,7 +3689,7 @@ class FunctionProtoType final private llvm::TrailingObjects< FunctionProtoType, QualType, FunctionType::FunctionTypeExtraBitfields, FunctionType::ExceptionType, Expr *, FunctionDecl *, - FunctionType::ExtParameterInfo, Qualifiers> { + FunctionType::ExtParameterInfo> { friend class ASTContext; // ASTContext creates these. friend TrailingObjects; @@ -3722,10 +3717,6 @@ class FunctionProtoType final // an ExtParameterInfo for each of the parameters. Present if and // only if hasExtParameterInfos() is true. // - // * Optionally a Qualifiers object to represent extra qualifiers that can't - // be represented by FunctionTypeBitfields.FastTypeQuals. Present if and only - // if hasExtQualifiers() is true. - // // The optional FunctionTypeExtraBitfields has to be before the data // related to the exception specification since it contains the number // of exception types. @@ -3772,7 +3763,7 @@ public: FunctionType::ExtInfo ExtInfo; bool Variadic : 1; bool HasTrailingReturn : 1; - Qualifiers TypeQuals; + unsigned char TypeQuals = 0; RefQualifierKind RefQualifier = RQ_None; ExceptionSpecInfo ExceptionSpec; const ExtParameterInfo *ExtParameterInfos = nullptr; @@ -3884,10 +3875,6 @@ private: return hasExtraBitfields(getExceptionSpecType()); } - bool hasExtQualifiers() const { - return FunctionTypeBits.HasExtQuals; - } - public: unsigned getNumParams() const { return FunctionTypeBits.NumParams; } @@ -3906,7 +3893,7 @@ public: EPI.Variadic = isVariadic(); EPI.HasTrailingReturn = hasTrailingReturn(); EPI.ExceptionSpec.Type = getExceptionSpecType(); - EPI.TypeQuals = getTypeQuals(); + EPI.TypeQuals = static_cast(getTypeQuals()); EPI.RefQualifier = getRefQualifier(); if (EPI.ExceptionSpec.Type == EST_Dynamic) { EPI.ExceptionSpec.Exceptions = exceptions(); @@ -4016,12 +4003,7 @@ public: /// Whether this function prototype has a trailing return type. bool hasTrailingReturn() const { return FunctionTypeBits.HasTrailingReturn; } - Qualifiers getTypeQuals() const { - if (hasExtQualifiers()) - return *getTrailingObjects(); - else - return getFastTypeQuals(); - } + unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); } /// Retrieve the ref-qualifier associated with this function type. RefQualifierKind getRefQualifier() const { diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 1d44e0d..e67e918 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5115,7 +5115,7 @@ public: /// using the given declaration (which is either a class template or a /// class) along with the given qualifiers. /// along with the qualifiers placed on '*this'. - CXXThisScopeRAII(Sema &S, Decl *ContextDecl, Qualifiers CXXThisTypeQuals, + CXXThisScopeRAII(Sema &S, Decl *ContextDecl, unsigned CXXThisTypeQuals, bool Enabled = true); ~CXXThisScopeRAII(); @@ -7752,7 +7752,7 @@ public: SourceLocation Loc, DeclarationName Entity, CXXRecordDecl *ThisContext, - Qualifiers ThisTypeQuals); + unsigned ThisTypeQuals); void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto, const MultiLevelTemplateArgumentList &Args); bool SubstExceptionSpec(SourceLocation Loc, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index fae1cf8..39ae9ce 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3768,11 +3768,10 @@ QualType ASTContext::getFunctionTypeInternal( size_t Size = FunctionProtoType::totalSizeToAlloc< QualType, FunctionType::FunctionTypeExtraBitfields, FunctionType::ExceptionType, Expr *, FunctionDecl *, - FunctionProtoType::ExtParameterInfo, Qualifiers>( + FunctionProtoType::ExtParameterInfo>( NumArgs, FunctionProtoType::hasExtraBitfields(EPI.ExceptionSpec.Type), ESH.NumExceptionType, ESH.NumExprPtr, ESH.NumFunctionDeclPtr, - EPI.ExtParameterInfos ? NumArgs : 0, - EPI.TypeQuals.hasNonFastQualifiers() ? 1 : 0); + EPI.ExtParameterInfos ? NumArgs : 0); auto *FTP = (FunctionProtoType *)Allocate(Size, TypeAlignment); FunctionProtoType::ExtProtoInfo newEPI = EPI; diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index 5b7713e..8137c81 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/lib/AST/ASTDumper.cpp @@ -199,10 +199,9 @@ namespace { void VisitFunctionProtoType(const FunctionProtoType *T) { auto EPI = T->getExtProtoInfo(); if (EPI.HasTrailingReturn) OS << " trailing_return"; - - if (!T->getTypeQuals().empty()) - OS << " " << T->getTypeQuals().getAsString(); - + if (T->isConst()) OS << " const"; + if (T->isVolatile()) OS << " volatile"; + if (T->isRestrict()) OS << " restrict"; switch (EPI.RefQualifier) { case RQ_None: break; case RQ_LValue: OS << " &"; break; diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 33f1594..419326ae 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2173,24 +2173,19 @@ CXXMethodDecl::overridden_methods() const { return getASTContext().overridden_methods(this); } -QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT, - const CXXRecordDecl *Decl) { - ASTContext &C = Decl->getASTContext(); - QualType ClassTy = C.getTypeDeclType(Decl); - ClassTy = C.getQualifiedType(ClassTy, FPT->getTypeQuals()); - return C.getPointerType(ClassTy); -} - QualType CXXMethodDecl::getThisType(ASTContext &C) const { // C++ 9.3.2p1: The type of this in a member function of a class X is X*. // If the member function is declared const, the type of this is const X*, // if the member function is declared volatile, the type of this is // volatile X*, and if the member function is declared const volatile, // the type of this is const volatile X*. + assert(isInstance() && "No 'this' for static methods!"); - return CXXMethodDecl::getThisType(getType()->getAs(), - getParent()); + QualType ClassTy = C.getTypeDeclType(getParent()); + ClassTy = C.getQualifiedType(ClassTy, + Qualifiers::fromCVRUMask(getTypeQualifiers())); + return C.getPointerType(ClassTy); } bool CXXMethodDecl::hasInlineBody() const { diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index d8d5621..a651bdb 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -1503,7 +1503,8 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, Out << 'N'; if (const CXXMethodDecl *Method = dyn_cast(ND)) { - Qualifiers MethodQuals = Method->getTypeQualifiers(); + Qualifiers MethodQuals = + Qualifiers::fromCVRUMask(Method->getTypeQualifiers()); // We do not consider restrict a distinguishing attribute for overloading // purposes so we must not mangle it. MethodQuals.removeRestrict(); @@ -2724,7 +2725,7 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) { // Mangle CV-qualifiers, if present. These are 'this' qualifiers, // e.g. "const" in "int (A::*)() const". - mangleQualifiers(T->getTypeQuals()); + mangleQualifiers(Qualifiers::fromCVRUMask(T->getTypeQuals())); // Mangle instantiation-dependent exception-specification, if present, // per cxx-abi-dev proposal on 2016-10-11. diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 821112e..b94524e 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -2093,7 +2093,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // If this is a C++ instance method, mangle the CVR qualifiers for the // this pointer. if (HasThisQuals) { - Qualifiers Quals = Proto->getTypeQuals(); + Qualifiers Quals = Qualifiers::fromCVRUMask(Proto->getTypeQuals()); manglePointerExtQualifiers(Quals, /*PointeeType=*/QualType()); mangleRefQualifier(Proto->getRefQualifier()); mangleQualifiers(Quals, /*IsMember=*/false); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 0dbc88c..b4e82d9 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2851,7 +2851,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef params, result->isInstantiationDependentType(), result->isVariablyModifiedType(), result->containsUnexpandedParameterPack(), epi.ExtInfo) { - FunctionTypeBits.FastTypeQuals = epi.TypeQuals.getFastQualifiers(); + FunctionTypeBits.TypeQuals = epi.TypeQuals; FunctionTypeBits.RefQualifier = epi.RefQualifier; FunctionTypeBits.NumParams = params.size(); assert(getNumParams() == params.size() && "NumParams overflow!"); @@ -2950,13 +2950,6 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef params, for (unsigned i = 0; i != getNumParams(); ++i) extParamInfos[i] = epi.ExtParameterInfos[i]; } - - if (epi.TypeQuals.hasNonFastQualifiers()) { - FunctionTypeBits.HasExtQuals = 1; - *getTrailingObjects() = epi.TypeQuals; - } else { - FunctionTypeBits.HasExtQuals = 0; - } } bool FunctionProtoType::hasDependentExceptionSpec() const { @@ -3048,13 +3041,14 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, // shortcut, use one AddInteger call instead of four for the next four // fields. assert(!(unsigned(epi.Variadic) & ~1) && + !(unsigned(epi.TypeQuals) & ~255) && !(unsigned(epi.RefQualifier) & ~3) && !(unsigned(epi.ExceptionSpec.Type) & ~15) && "Values larger than expected."); ID.AddInteger(unsigned(epi.Variadic) + - (epi.RefQualifier << 1) + - (epi.ExceptionSpec.Type << 3)); - ID.Add(epi.TypeQuals); + (epi.TypeQuals << 1) + + (epi.RefQualifier << 9) + + (epi.ExceptionSpec.Type << 11)); if (epi.ExceptionSpec.Type == EST_Dynamic) { for (QualType Ex : epi.ExceptionSpec.Exceptions) ID.AddPointer(Ex.getAsOpaquePtr()); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 031b44f..7ae2ad8 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -801,8 +801,10 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, printFunctionAfter(Info, OS); - if (!T->getTypeQuals().empty()) - OS << " " << T->getTypeQuals().getAsString(); + if (unsigned quals = T->getTypeQuals()) { + OS << ' '; + AppendTypeQualList(OS, quals, Policy.Restrict); + } switch (T->getRefQualifier()) { case RQ_None: diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 26e6104..4757cd2 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -68,13 +68,11 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { } } -/// Derives the 'this' type for codegen purposes, i.e. ignoring method CVR +/// Derives the 'this' type for codegen purposes, i.e. ignoring method /// qualification. -static CanQualType GetThisType(ASTContext &Context, const CXXRecordDecl *RD, - const CXXMethodDecl *MD) { +/// FIXME: address space qualification? +static CanQualType GetThisType(ASTContext &Context, const CXXRecordDecl *RD) { QualType RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal(); - if (MD) - RecTy = Context.getAddrSpaceQualType(RecTy, MD->getType().getAddressSpace()); return Context.getPointerType(CanQualType::CreateUnsafe(RecTy)); } @@ -252,7 +250,7 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD, // Add the 'this' pointer. if (RD) - argTypes.push_back(GetThisType(Context, RD, MD)); + argTypes.push_back(GetThisType(Context, RD)); else argTypes.push_back(Context.VoidPtrTy); @@ -308,7 +306,7 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD, SmallVector argTypes; SmallVector paramInfos; - argTypes.push_back(GetThisType(Context, MD->getParent(), MD)); + argTypes.push_back(GetThisType(Context, MD->getParent())); bool PassParams = true; @@ -535,7 +533,7 @@ const CGFunctionInfo & CodeGenTypes::arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD) { assert(MD->isVirtual() && "only methods have thunks"); CanQual FTP = GetFormalType(MD); - CanQualType ArgTys[] = { GetThisType(Context, MD->getParent(), MD) }; + CanQualType ArgTys[] = { GetThisType(Context, MD->getParent()) }; return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false, /*chainCall=*/false, ArgTys, FTP->getExtInfo(), {}, RequiredArgs(1)); @@ -549,7 +547,7 @@ CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD, CanQual FTP = GetFormalType(CD); SmallVector ArgTys; const CXXRecordDecl *RD = CD->getParent(); - ArgTys.push_back(GetThisType(Context, RD, CD)); + ArgTys.push_back(GetThisType(Context, RD)); if (CT == Ctor_CopyingClosure) ArgTys.push_back(*FTP->param_type_begin()); if (RD->getNumVBases() > 0) diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index cfc912c..28ae555 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -16,7 +16,6 @@ #include "CGDebugInfo.h" #include "CGRecordLayout.h" #include "CodeGenFunction.h" -#include "TargetInfo.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/EvaluatedExprVisitor.h" @@ -2013,19 +2012,8 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, bool NewPointerIsChecked) { CallArgList Args; - LangAS SlotAS = E->getType().getAddressSpace(); - QualType ThisType = D->getThisType(getContext()); - LangAS ThisAS = ThisType.getTypePtr()->getPointeeType().getAddressSpace(); - llvm::Value *ThisPtr = This.getPointer(); - if (SlotAS != ThisAS) { - unsigned TargetThisAS = getContext().getTargetAddressSpace(ThisAS); - llvm::Type *NewType = - ThisPtr->getType()->getPointerElementType()->getPointerTo(TargetThisAS); - ThisPtr = getTargetHooks().performAddrSpaceCast(*this, This.getPointer(), - ThisAS, SlotAS, NewType); - } // Push the this ptr. - Args.add(RValue::get(ThisPtr), D->getThisType(getContext())); + Args.add(RValue::get(This.getPointer()), D->getThisType(getContext())); // If this is a trivial constructor, emit a memcpy now before we lose // the alignment information on the argument. diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index e45b38c..3f0837e 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2617,9 +2617,9 @@ llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty, const FunctionProtoType *FPT = Ty->getPointeeType()->getAs(); return DBuilder.createMemberPointerType( - getOrCreateInstanceMethodType( - CXXMethodDecl::getThisType(FPT, Ty->getMostRecentCXXRecordDecl()), - FPT, U), + getOrCreateInstanceMethodType(CGM.getContext().getPointerType(QualType( + Ty->getClass(), FPT->getTypeQuals())), + FPT, U), ClassType, Size, /*Align=*/0, Flags); } diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 9aa31f1..08ceaa9 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -26,10 +26,7 @@ using namespace CodeGen; static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D, ConstantAddress DeclPtr) { - assert( - (D.hasGlobalStorage() || - (D.hasLocalStorage() && CGF.getContext().getLangOpts().OpenCLCPlusPlus)) && - "VarDecl must have global or local (in the case of OpenCL) storage!"); + assert(D.hasGlobalStorage() && "VarDecl must have global storage!"); assert(!D.getType()->isReferenceType() && "Should not call EmitDeclInit on a reference!"); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 6ef1091..b6f26a6 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3948,7 +3948,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, LValue RefLVal = MakeAddrLValue(addr, FieldType, FieldBaseInfo, FieldTBAAInfo); if (RecordCVR & Qualifiers::Volatile) - RefLVal.getQuals().addVolatile(); + RefLVal.getQuals().setVolatile(true); addr = EmitLoadOfReference(RefLVal, &FieldBaseInfo, &FieldTBAAInfo); // Qualifiers on the struct don't apply to the referencee. diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h index da8a8ef..0dcbea4 100644 --- a/clang/lib/CodeGen/CGValue.h +++ b/clang/lib/CodeGen/CGValue.h @@ -562,10 +562,7 @@ public: } void setVolatile(bool flag) { - if (flag) - Quals.addVolatile(); - else - Quals.removeVolatile(); + Quals.setVolatile(flag); } Qualifiers::ObjCLifetime getObjCLifetime() const { diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp index 84ca753..2c3c186 100644 --- a/clang/lib/Index/USRGeneration.cpp +++ b/clang/lib/Index/USRGeneration.cpp @@ -270,8 +270,7 @@ void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) { if (const CXXMethodDecl *MD = dyn_cast(D)) { if (MD->isStatic()) Out << 'S'; - // FIXME: OpenCL: Need to consider address spaces - if (unsigned quals = MD->getTypeQualifiers().getCVRUQualifiers()) + if (unsigned quals = MD->getTypeQualifiers()) Out << (char)('0' + quals); switch (MD->getRefQualifier()) { case RQ_None: break; diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index fde3ce0..848a09b 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -595,7 +595,7 @@ void Parser::ParseLexedMemberInitializers(ParsingClass &Class) { // to X" within the optional brace-or-equal-initializer. It shall not // appear elsewhere in the member-declarator. Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate, - Qualifiers()); + /*TypeQuals=*/(unsigned)0); for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers(); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index caf443d..bff9179 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1427,7 +1427,7 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, RecordDecl *RD = dyn_cast_or_null(D->getDeclContext()); // Allow 'this' within late-parsed attributes. - Sema::CXXThisScopeRAII ThisScope(Actions, RD, Qualifiers(), + Sema::CXXThisScopeRAII ThisScope(Actions, RD, /*TypeQuals=*/0, ND && ND->isCXXInstanceMember()); if (LA.Decls.size() == 1) { @@ -6162,14 +6162,13 @@ void Parser::ParseFunctionDeclarator(Declarator &D, : D.getContext() == DeclaratorContext::FileContext && D.getCXXScopeSpec().isValid() && Actions.CurContext->isRecord()); - - Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers()); - if (D.getDeclSpec().isConstexprSpecified() && !getLangOpts().CPlusPlus14) - Q.addConst(); - - Sema::CXXThisScopeRAII ThisScope( - Actions, dyn_cast(Actions.CurContext), Q, - IsCXX11MemberFunction); + Sema::CXXThisScopeRAII ThisScope(Actions, + dyn_cast(Actions.CurContext), + DS.getTypeQualifiers() | + (D.getDeclSpec().isConstexprSpecified() && + !getLangOpts().CPlusPlus14 + ? Qualifiers::Const : 0), + IsCXX11MemberFunction); // Parse exception-specification[opt]. bool Delayed = D.isFirstDeclarationOfMember() && diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 1fb5280..475b20c 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -495,7 +495,7 @@ public: Sema &Actions = P.getActions(); // Allow 'this' within late-parsed attributes. - ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(), + ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0, ND && ND->isCXXInstanceMember()); // If the Decl is templatized, add template parameters to scope. diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 6d310ca..7a8f31f0 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -1028,7 +1028,8 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, if (HasObjectTypeQualifiers) if (const auto *Method = dyn_cast(R.Declaration)) if (Method->isInstance()) { - Qualifiers MethodQuals = Method->getTypeQualifiers(); + Qualifiers MethodQuals = + Qualifiers::fromCVRMask(Method->getTypeQualifiers()); if (ObjectTypeQualifiers == MethodQuals) R.Priority += CCD_ObjectQualifierMatch; else if (ObjectTypeQualifiers - MethodQuals) { @@ -2742,17 +2743,17 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, // FIXME: Add ref-qualifier! // Handle single qualifiers without copying - if (Proto->getTypeQuals().hasOnlyConst()) { + if (Proto->getTypeQuals() == Qualifiers::Const) { Result.AddInformativeChunk(" const"); return; } - if (Proto->getTypeQuals().hasOnlyVolatile()) { + if (Proto->getTypeQuals() == Qualifiers::Volatile) { Result.AddInformativeChunk(" volatile"); return; } - if (Proto->getTypeQuals().hasOnlyRestrict()) { + if (Proto->getTypeQuals() == Qualifiers::Restrict) { Result.AddInformativeChunk(" restrict"); return; } @@ -3737,7 +3738,8 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, // the member function to filter/prioritize the results list. if (CXXMethodDecl *CurMethod = dyn_cast(CurContext)) { if (CurMethod->isInstance()) { - Results.setObjectTypeQualifiers(CurMethod->getTypeQualifiers()); + Results.setObjectTypeQualifiers( + Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers())); } } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6dab332..ba7bcda 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3192,12 +3192,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, if (RequiresAdjustment) { const FunctionType *AdjustedType = New->getType()->getAs(); AdjustedType = Context.adjustFunctionType(AdjustedType, NewTypeInfo); - - QualType AdjustedQT = QualType(AdjustedType, 0); - LangAS AS = Old->getType().getAddressSpace(); - AdjustedQT = Context.getAddrSpaceQualType(AdjustedQT, AS); - - New->setType(AdjustedQT); + New->setType(QualType(AdjustedType, 0)); NewQType = Context.getCanonicalType(New->getType()); NewType = cast(NewQType); } @@ -10022,7 +10017,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, CXXMethodDecl *MD = dyn_cast(NewFD); if (!getLangOpts().CPlusPlus14 && MD && MD->isConstexpr() && !MD->isStatic() && !isa(MD) && - !MD->getTypeQualifiers().hasConst()) { + (MD->getTypeQualifiers() & Qualifiers::Const) == 0) { CXXMethodDecl *OldMD = nullptr; if (OldDecl) OldMD = dyn_cast_or_null(OldDecl->getAsFunction()); @@ -10030,7 +10025,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, const FunctionProtoType *FPT = MD->getType()->castAs(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - EPI.TypeQuals.addConst(); + EPI.TypeQuals |= Qualifiers::Const; MD->setType(Context.getFunctionType(FPT->getReturnType(), FPT->getParamTypes(), EPI)); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 4a7ab11..7914a5d 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8199,7 +8199,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, return R; FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); - EPI.TypeQuals = Qualifiers(); + EPI.TypeQuals = 0; EPI.RefQualifier = RQ_None; return Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI); @@ -8405,7 +8405,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, const FunctionProtoType *Proto = R->getAs(); FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); EPI.Variadic = false; - EPI.TypeQuals = Qualifiers(); + EPI.TypeQuals = 0; EPI.RefQualifier = RQ_None; return Context.getFunctionType(Context.VoidTy, None, EPI); } @@ -11991,7 +11991,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // Dereference "this". DerefBuilder DerefThis(This); CastBuilder To(DerefThis, - Context.getQualifiedType( + Context.getCVRQualifiedType( BaseType, CopyAssignOperator->getTypeQualifiers()), VK_LValue, BasePath); @@ -12358,7 +12358,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, // Implicitly cast "this" to the appropriately-qualified base type. CastBuilder To(DerefThis, - Context.getQualifiedType( + Context.getCVRQualifiedType( BaseType, MoveAssignOperator->getTypeQualifiers()), VK_LValue, BasePath); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2705a67..29a2f05 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -13553,7 +13553,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, // Drop the parameters. FunctionProtoType::ExtProtoInfo EPI; EPI.HasTrailingReturn = false; - EPI.TypeQuals.addConst(); + EPI.TypeQuals |= DeclSpec::TQ_const; T = Context.getFunctionType(Context.DependentTy, None, EPI); Sig = Context.getTrivialTypeSourceInfo(T); } @@ -13729,7 +13729,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, } else { const FunctionProtoType *FPT = cast(FTy); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - EPI.TypeQuals = Qualifiers(); + EPI.TypeQuals = 0; // FIXME: silently? EPI.ExtInfo = Ext; BlockTy = Context.getFunctionType(RetTy, FPT->getParamTypes(), EPI); } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 2b054c4..ceb55d9 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1094,7 +1094,7 @@ QualType Sema::getCurrentThisType() { Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S, Decl *ContextDecl, - Qualifiers CXXThisTypeQuals, + unsigned CXXThisTypeQuals, bool Enabled) : S(S), OldCXXThisTypeOverride(S.CXXThisTypeOverride), Enabled(false) { @@ -1107,10 +1107,11 @@ Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S, else Record = cast(ContextDecl); - QualType T = S.Context.getRecordType(Record); - T = S.getASTContext().getQualifiedType(T, CXXThisTypeQuals); - - S.CXXThisTypeOverride = S.Context.getPointerType(T); + // We care only for CVR qualifiers here, so cut everything else. + CXXThisTypeQuals &= Qualifiers::FastMask; + S.CXXThisTypeOverride + = S.Context.getPointerType( + S.Context.getRecordType(Record).withCVRQualifiers(CXXThisTypeQuals)); this->Enabled = true; } diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 6dc93d0..2ff6137 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -859,7 +859,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true)); EPI.HasTrailingReturn = true; - EPI.TypeQuals.addConst(); + EPI.TypeQuals |= DeclSpec::TQ_const; // C++1y [expr.prim.lambda]: // The lambda return type is 'auto', which is replaced by the // trailing-return type if provided and/or deduced from 'return' @@ -1198,7 +1198,7 @@ QualType Sema::getLambdaConversionFunctionResultType( CallingConv CC = Context.getDefaultCallingConvention( CallOpProto->isVariadic(), /*IsCXXMethod=*/false); InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC); - InvokerExtInfo.TypeQuals = Qualifiers(); + InvokerExtInfo.TypeQuals = 0; assert(InvokerExtInfo.RefQualifier == RQ_None && "Lambda's call operator should not have a reference qualifier"); return Context.getFunctionType(CallOpProto->getReturnType(), @@ -1229,8 +1229,7 @@ static void addFunctionPointerConversion(Sema &S, S.Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true)); // The conversion function is always const. - ConvExtInfo.TypeQuals = Qualifiers(); - ConvExtInfo.TypeQuals.addConst(); + ConvExtInfo.TypeQuals = Qualifiers::Const; QualType ConvTy = S.Context.getFunctionType(PtrToFunctionTy, None, ConvExtInfo); @@ -1378,8 +1377,7 @@ static void addBlockPointerConversion(Sema &S, FunctionProtoType::ExtProtoInfo ConversionEPI( S.Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true)); - ConversionEPI.TypeQuals = Qualifiers(); - ConversionEPI.TypeQuals.addConst(); + ConversionEPI.TypeQuals = Qualifiers::Const; QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ConversionEPI); SourceLocation Loc = IntroducerRange.getBegin(); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 2c0516c..22514ee 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1142,9 +1142,8 @@ 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(); + unsigned OldQuals = OldMethod->getTypeQualifiers(); + unsigned NewQuals = NewMethod->getTypeQualifiers(); if (!getLangOpts().CPlusPlus14 && NewMethod->isConstexpr() && !isa(NewMethod)) NewQuals |= Qualifiers::Const; @@ -2824,9 +2823,8 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, return; } - // FIXME: OpenCL: Need to consider address spaces - unsigned FromQuals = FromFunction->getTypeQuals().getCVRUQualifiers(); - unsigned ToQuals = ToFunction->getTypeQuals().getCVRUQualifiers(); + unsigned FromQuals = FromFunction->getTypeQuals(), + ToQuals = ToFunction->getTypeQuals(); if (FromQuals != ToQuals) { PDiag << ft_qualifer_mismatch << ToQuals << FromQuals; return; @@ -5067,15 +5065,9 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType, QualType ClassType = S.Context.getTypeDeclType(ActingContext); // [class.dtor]p2: A destructor can be invoked for a const, volatile or // const volatile object. - Qualifiers Quals; - if (isa(Method)) { - Quals.addConst(); - Quals.addVolatile(); - } else { - Quals = Method->getTypeQualifiers(); - } - - QualType ImplicitParamType = S.Context.getQualifiedType(ClassType, Quals); + unsigned Quals = isa(Method) ? + Qualifiers::Const | Qualifiers::Volatile : Method->getTypeQualifiers(); + QualType ImplicitParamType = S.Context.getCVRQualifiedType(ClassType, Quals); // Set up the conversion sequence as a "bad" conversion, to allow us // to exit early. @@ -5141,7 +5133,7 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType, break; case RQ_LValue: - if (!FromClassification.isLValue() && !Quals.hasOnlyConst()) { + if (!FromClassification.isLValue() && Quals != Qualifiers::Const) { // non-const lvalue reference cannot bind to an rvalue ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, FromType, ImplicitParamType); @@ -5257,14 +5249,9 @@ Sema::PerformObjectArgumentInitialization(Expr *From, From = FromRes.get(); } - if (!Context.hasSameType(From->getType(), DestType)) { - if (From->getType().getAddressSpace() != DestType.getAddressSpace()) - From = ImpCastExprToType(From, DestType, CK_AddressSpaceConversion, + if (!Context.hasSameType(From->getType(), DestType)) + From = ImpCastExprToType(From, DestType, CK_NoOp, From->getValueKind()).get(); - else - From = ImpCastExprToType(From, DestType, CK_NoOp, - From->getValueKind()).get(); - } return From; } @@ -12839,7 +12826,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Check that the object type isn't more qualified than the // member function we're calling. - Qualifiers funcQuals = proto->getTypeQuals(); + Qualifiers funcQuals = Qualifiers::fromCVRMask(proto->getTypeQuals()); QualType objectType = op->getLHS()->getType(); if (op->getOpcode() == BO_PtrMemI) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c176352..a3dbb44 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8135,7 +8135,7 @@ bool Sema::CheckFunctionTemplateSpecialization( if (OldMD && OldMD->isConst()) { const FunctionProtoType *FPT = FT->castAs(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - EPI.TypeQuals.addConst(); + EPI.TypeQuals |= Qualifiers::Const; FT = Context.getFunctionType(FPT->getReturnType(), FPT->getParamTypes(), EPI); } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 155d842..c96bf10 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3078,7 +3078,7 @@ Sema::SubstituteExplicitTemplateArguments( // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq // and the end of the function-definition, member-declarator, or // declarator. - Qualifiers ThisTypeQuals; + unsigned ThisTypeQuals = 0; CXXRecordDecl *ThisContext = nullptr; if (CXXMethodDecl *Method = dyn_cast(Function)) { ThisContext = Method->getParent(); @@ -4657,7 +4657,8 @@ AddImplicitObjectParameterType(ASTContext &Context, // The standard doesn't say explicitly, but we pick the appropriate kind of // reference type based on [over.match.funcs]p4. QualType ArgTy = Context.getTypeDeclType(Method->getParent()); - ArgTy = Context.getQualifiedType(ArgTy, Method->getTypeQualifiers()); + ArgTy = Context.getQualifiedType(ArgTy, + Qualifiers::fromCVRMask(Method->getTypeQualifiers())); if (Method->getRefQualifier() == RQ_RValue) ArgTy = Context.getRValueReferenceType(ArgTy); else diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 96abeed..8dde68f 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -907,7 +907,7 @@ namespace { QualType TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext, - Qualifiers ThisTypeQuals, + unsigned ThisTypeQuals, Fn TransformExceptionSpec); ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, @@ -1427,7 +1427,7 @@ template QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext, - Qualifiers ThisTypeQuals, + unsigned ThisTypeQuals, Fn TransformExceptionSpec) { // We need a local instantiation scope for this function prototype. LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true); @@ -1666,7 +1666,7 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, SourceLocation Loc, DeclarationName Entity, CXXRecordDecl *ThisContext, - Qualifiers ThisTypeQuals) { + unsigned ThisTypeQuals) { assert(!CodeSynthesisContexts.empty() && "Cannot perform an instantiation without some context on the " "instantiation stack"); @@ -2148,7 +2148,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, NamedDecl *ND = dyn_cast(I->NewDecl); CXXRecordDecl *ThisContext = dyn_cast_or_null(ND->getDeclContext()); - CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(), + CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0, ND && ND->isCXXInstanceMember()); Attr *NewAttr = @@ -2343,7 +2343,7 @@ bool Sema::InstantiateInClassInitializer( // Instantiate the initializer. ActOnStartCXXInClassMemberInitializer(); - CXXThisScopeRAII ThisScope(*this, Instantiation->getParent(), Qualifiers()); + CXXThisScopeRAII ThisScope(*this, Instantiation->getParent(), /*TypeQuals=*/0); ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs, /*CXXDirectInit=*/false); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 31353e4..8f9af03 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -295,7 +295,7 @@ static void instantiateOMPDeclareSimdDeclAttr( PVD, FD->getParamDecl(PVD->getFunctionScopeIndex())); return S.SubstExpr(E, TemplateArgs); } - Sema::CXXThisScopeRAII ThisScope(S, ThisContext, Qualifiers(), + Sema::CXXThisScopeRAII ThisScope(S, ThisContext, /*TypeQuals=*/0, FD->isCXXInstanceMember()); return S.SubstExpr(E, TemplateArgs); }; @@ -355,7 +355,7 @@ void Sema::InstantiateAttrsForDecl( // applicable to template declaration, we'll need to add them here. CXXThisScopeRAII ThisScope( *this, dyn_cast_or_null(ND->getDeclContext()), - Qualifiers(), ND->isCXXInstanceMember()); + /*TypeQuals*/ 0, ND->isCXXInstanceMember()); Attr *NewAttr = sema::instantiateTemplateAttributeForDecl( TmplAttr, Context, *this, TemplateArgs); @@ -474,7 +474,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, NamedDecl *ND = dyn_cast(New); CXXRecordDecl *ThisContext = dyn_cast_or_null(ND->getDeclContext()); - CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(), + CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0, ND && ND->isCXXInstanceMember()); Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, @@ -2822,7 +2822,7 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( cast(D->getCombinerOut())->getDecl(), cast(NewDRD->getCombinerOut())->getDecl()); auto *ThisContext = dyn_cast_or_null(Owner); - Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(), + Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, /*TypeQuals*/ 0, ThisContext); SubstCombiner = SemaRef.SubstExpr(D->getCombiner(), TemplateArgs).get(); SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner); @@ -3441,7 +3441,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, assert(Params.empty() && "parameter vector is non-empty at start"); CXXRecordDecl *ThisContext = nullptr; - Qualifiers ThisTypeQuals; + unsigned ThisTypeQuals = 0; if (CXXMethodDecl *Method = dyn_cast(D)) { ThisContext = cast(Owner); ThisTypeQuals = Method->getTypeQualifiers(); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index bd4a0e1..20d9bb8 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1873,7 +1873,8 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type, } static std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy){ - std::string Quals = FnTy->getTypeQuals().getAsString(); + std::string Quals = + Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString(); switch (FnTy->getRefQualifier()) { case RQ_None: @@ -1915,7 +1916,7 @@ static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc, QualifiedFunctionKind QFK) { // Does T refer to a function type with a cv-qualifier or a ref-qualifier? const FunctionProtoType *FPT = T->getAs(); - if (!FPT || (FPT->getTypeQuals().empty() && FPT->getRefQualifier() == RQ_None)) + if (!FPT || (FPT->getTypeQuals() == 0 && FPT->getRefQualifier() == RQ_None)) return false; S.Diag(Loc, diag::err_compound_qualified_function_type) @@ -3949,7 +3950,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Does T refer to a function type with a cv-qualifier or a ref-qualifier? bool IsQualifiedFunction = T->isFunctionProtoType() && - (!T->castAs()->getTypeQuals().empty() || + (T->castAs()->getTypeQuals() != 0 || T->castAs()->getRefQualifier() != RQ_None); // If T is 'decltype(auto)', the only declarators we can have are parens @@ -4698,7 +4699,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, EPI.ExtInfo = EI; EPI.Variadic = FTI.isVariadic; EPI.HasTrailingReturn = FTI.hasTrailingReturnType(); - EPI.TypeQuals.addCVRUQualifiers(FTI.TypeQuals); + EPI.TypeQuals = FTI.TypeQuals; EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None : FTI.RefQualifierIsLValueRef? RQ_LValue : RQ_RValue; @@ -4825,24 +4826,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, Exceptions, EPI.ExceptionSpec); - const auto &Spec = D.getCXXScopeSpec(); - // 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(); - // If a class member function's address space is not set, set it to - // __generic. - LangAS AS = - (CurAS == LangAS::Default ? LangAS::opencl_generic : CurAS); - EPI.TypeQuals.addAddressSpace(AS); - T = Context.getFunctionType(T, ParamTys, EPI); - T = state.getSema().Context.getAddrSpaceQualType(T, AS); - } else { - T = Context.getFunctionType(T, ParamTys, EPI); - } + T = Context.getFunctionType(T, ParamTys, EPI); } break; } @@ -5047,7 +5031,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Strip the cv-qualifiers and ref-qualifiers from the type. FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo(); - EPI.TypeQuals.removeCVRQualifiers(); + EPI.TypeQuals = 0; EPI.RefQualifier = RQ_None; T = Context.getFunctionType(FnTy->getReturnType(), FnTy->getParamTypes(), diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3f4b21e..bbc5fab 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -597,7 +597,7 @@ public: QualType TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext, - Qualifiers ThisTypeQuals, + unsigned ThisTypeQuals, Fn TransformExceptionSpec); bool TransformExceptionSpec(SourceLocation Loc, @@ -4274,11 +4274,8 @@ QualType TreeTransform::RebuildQualifiedType(QualType T, // C++ [dcl.fct]p7: // [When] adding cv-qualifications on top of the function type [...] the // cv-qualifiers are ignored. - if (T->isFunctionType()) { - T = SemaRef.getASTContext().getAddrSpaceQualType(T, - Quals.getAddressSpace()); + if (T->isFunctionType()) return T; - } // C++ [dcl.ref]p1: // when the cv-qualifiers are introduced through the use of a typedef-name @@ -5245,7 +5242,7 @@ TreeTransform::TransformFunctionProtoType(TypeLocBuilder &TLB, SmallVector ExceptionStorage; TreeTransform *This = this; // Work around gcc.gnu.org/PR56135. return getDerived().TransformFunctionProtoType( - TLB, TL, nullptr, Qualifiers(), + TLB, TL, nullptr, 0, [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) { return This->TransformExceptionSpec(TL.getBeginLoc(), ESI, ExceptionStorage, Changed); @@ -5255,7 +5252,7 @@ TreeTransform::TransformFunctionProtoType(TypeLocBuilder &TLB, template template QualType TreeTransform::TransformFunctionProtoType( TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext, - Qualifiers ThisTypeQuals, Fn TransformExceptionSpec) { + unsigned ThisTypeQuals, Fn TransformExceptionSpec) { // Transform the parameters and return type. // @@ -11027,7 +11024,7 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { SmallVector ExceptionStorage; TreeTransform *This = this; // Work around gcc.gnu.org/PR56135. QualType NewCallOpType = TransformFunctionProtoType( - NewCallOpTLBuilder, OldCallOpFPTL, nullptr, Qualifiers(), + NewCallOpTLBuilder, OldCallOpFPTL, nullptr, 0, [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) { return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI, ExceptionStorage, Changed); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 558100d..67ab601 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6050,7 +6050,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) { EPI.Variadic = Record[Idx++]; EPI.HasTrailingReturn = Record[Idx++]; - EPI.TypeQuals = Qualifiers::fromOpaqueValue(Record[Idx++]); + EPI.TypeQuals = Record[Idx++]; EPI.RefQualifier = static_cast(Record[Idx++]); SmallVector ExceptionStorage; readExceptionSpec(*Loc.F, ExceptionStorage, EPI.ExceptionSpec, Record, Idx); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 45de91f..7ae7569 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -310,7 +310,7 @@ void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) { Record.push_back(T->isVariadic()); Record.push_back(T->hasTrailingReturn()); - Record.push_back(T->getTypeQuals().getAsOpaqueValue()); + Record.push_back(T->getTypeQuals()); Record.push_back(static_cast(T->getRefQualifier())); addExceptionSpec(T, Record); diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl b/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl deleted file mode 100644 index af0e3b1..0000000 --- a/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl +++ /dev/null @@ -1,154 +0,0 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -pedantic -verify -O0 -o - | FileCheck %s -// expected-no-diagnostics - -// Test that the 'this' pointer is in the __generic address space. - -// FIXME: Add support for __constant address space. - -class C { -public: - int v; - C() { v = 2; } - // FIXME: Does not work yet. - // C(C &&c) { v = c.v; } - C(const C &c) { v = c.v; } - C &operator=(const C &c) { - v = c.v; - return *this; - } - // FIXME: Does not work yet. - //C &operator=(C&& c) & { - // v = c.v; - // return *this; - //} - - int get() { return v; } - - int outside(); -}; - -int C::outside() { - return v; -} - -extern C&& foo(); - -__global C c; - -__kernel void test__global() { - int i = c.get(); - int i2 = c.outside(); - C c1(c); - C c2; - c2 = c1; - // FIXME: Does not work yet. - // C c3 = c1 + c2; - // C c4(foo()); - // C c5 = foo(); - -} - -// CHECK-LABEL: @__cxx_global_var_init() -// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) #4 - -// Test that the address space is __generic for the constructor -// CHECK-LABEL: @_ZNU3AS41CC1Ev(%class.C addrspace(4)* %this) -// CHECK: entry: -// CHECK: %this.addr = alloca %class.C addrspace(4)*, align 4 -// CHECK: store %class.C addrspace(4)* %this, %class.C addrspace(4)** %this.addr, align 4 -// CHECK: %this1 = load %class.C addrspace(4)*, %class.C addrspace(4)** %this.addr, align 4 -// CHECK: call void @_ZNU3AS41CC2Ev(%class.C addrspace(4)* %this1) #4 -// CHECK: ret void - -// CHECK-LABEL: @_Z12test__globalv() - -// Test the address space of 'this' when invoking a method. -// CHECK: %call = call i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) - -// Test the address space of 'this' when invoking a method that is declared in the file contex. -// CHECK: %call1 = call i32 @_ZNU3AS41C7outsideEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) - -// Test the address space of 'this' when invoking copy-constructor. -// CHECK: %0 = addrspacecast %class.C* %c1 to %class.C addrspace(4)* -// CHECK: call void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* %0, %class.C addrspace(4)* dereferenceable(4) addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) - -// Test the address space of 'this' when invoking a constructor. -// CHECK: %1 = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* %1) #4 - -// Test the address space of 'this' when invoking assignment operator. -// CHECK: %2 = addrspacecast %class.C* %c1 to %class.C addrspace(4)* -// CHECK: %3 = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// CHECK: %call2 = call dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* %3, %class.C addrspace(4)* dereferenceable(4) %2) - -#define TEST(AS) \ - __kernel void test##AS() { \ - AS C c; \ - int i = c.get(); \ - C c1(c); \ - C c2; \ - c2 = c1; \ - } - -TEST(__local) - -// CHECK-LABEL: _Z11test__localv -// CHECK: @__cxa_guard_acquire - -// Test the address space of 'this' when invoking a method. -// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* addrspacecast (%class.C addrspace(3)* @_ZZ11test__localvE1c to %class.C addrspace(4)*)) - -// Test the address space of 'this' when invoking copy-constructor. -// CHECK: %call = call i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(3)* @_ZZ11test__localvE1c to %class.C addrspace(4)*)) - -// Test the address space of 'this' when invoking a constructor. -// CHECK: %3 = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* %3) - -// Test the address space of 'this' when invoking assignment operator. -// CHECK: %4 = addrspacecast %class.C* %c1 to %class.C addrspace(4)* -// CHECK: %5 = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// CHECK: %call1 = call dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* %5, %class.C addrspace(4)* dereferenceable(4) %4) - -TEST(__private) - -// CHECK-LABEL: @_Z13test__privatev - -// Test the address space of 'this' when invoking a method. -// CHECK: %1 = addrspacecast %class.C* %c to %class.C addrspace(4)* -// CHECK: %call = call i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* %1) - -// Test the address space of 'this' when invoking a copy-constructor. -// CHECK: %2 = addrspacecast %class.C* %c1 to %class.C addrspace(4)* -// CHECK: %3 = addrspacecast %class.C* %c to %class.C addrspace(4)* -// CHECK: call void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* %2, %class.C addrspace(4)* dereferenceable(4) %3) - -// Test the address space of 'this' when invoking a constructor. -// CHECK: %4 = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* %4) - -// Test the address space of 'this' when invoking a copy-assignment. -// CHECK: %5 = addrspacecast %class.C* %c1 to %class.C addrspace(4)* -// CHECK: %6 = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// CHECK: %call1 = call dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* %6, %class.C addrspace(4)* dereferenceable(4) %5) - -TEST() - -// CHECK-LABEL: @_Z4testv() -// Test the address space of 'this' when invoking a method. -// CHECK: %1 = addrspacecast %class.C* %c to %class.C addrspace(4)* -// CHECK: %call = call i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* %1) #4 - -// Test the address space of 'this' when invoking a copy-constructor. -// CHECK: %2 = addrspacecast %class.C* %c1 to %class.C addrspace(4)* -// CHECK: %3 = addrspacecast %class.C* %c to %class.C addrspace(4)* -// CHECK: call void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* %2, %class.C addrspace(4)* dereferenceable(4) %3) - -// Test the address space of 'this' when invoking a constructor. -// CHECK: %4 = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// CHECK: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* %4) - -// Test the address space of 'this' when invoking a copy-assignment. -// CHECK: %5 = addrspacecast %class.C* %c1 to %class.C addrspace(4)* -// CHECK: %6 = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// CHECK: %call1 = call dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* %6, %class.C addrspace(4)* dereferenceable(4) %5) diff --git a/clang/test/CodeGenOpenCLCXX/template-address-spaces.cl b/clang/test/CodeGenOpenCLCXX/template-address-spaces.cl index 7c72253..eb274ea 100644 --- a/clang/test/CodeGenOpenCLCXX/template-address-spaces.cl +++ b/clang/test/CodeGenOpenCLCXX/template-address-spaces.cl @@ -9,16 +9,13 @@ struct S{ template T S::foo() { return a;} -// CHECK: %struct.S = type { i32 } -// CHECK: %struct.S.0 = type { i32 addrspace(4)* } -// CHECK: %struct.S.1 = type { i32 addrspace(1)* } +//CHECK: %struct.S = type { i32 } +//CHECK: %struct.S.0 = type { i32 addrspace(4)* } +//CHECK: %struct.S.1 = type { i32 addrspace(1)* } -// CHECK: %0 = addrspacecast %struct.S* %sint to %struct.S addrspace(4)* -// CHECK: %call = call i32 @_ZNU3AS41SIiE3fooEv(%struct.S addrspace(4)* %0) #1 -// CHECK: %1 = addrspacecast %struct.S.0* %sintptr to %struct.S.0 addrspace(4)* -// CHECK: %call1 = call i32 addrspace(4)* @_ZNU3AS41SIPU3AS4iE3fooEv(%struct.S.0 addrspace(4)* %1) #1 -// CHECK: %2 = addrspacecast %struct.S.1* %sintptrgl to %struct.S.1 addrspace(4)* -// CHECK: %call2 = call i32 addrspace(1)* @_ZNU3AS41SIPU3AS1iE3fooEv(%struct.S.1 addrspace(4)* %2) #1 +//CHECK: i32 @_ZN1SIiE3fooEv(%struct.S* %this) +//CHECK: i32 addrspace(4)* @_ZN1SIPU3AS4iE3fooEv(%struct.S.0* %this) +//CHECK: i32 addrspace(1)* @_ZN1SIPU3AS1iE3fooEv(%struct.S.1* %this) void bar(){ S sint; diff --git a/clang/test/SemaOpenCLCXX/address-space-templates.cl b/clang/test/SemaOpenCLCXX/address-space-templates.cl index 80762fc..48fbdc7 100644 --- a/clang/test/SemaOpenCLCXX/address-space-templates.cl +++ b/clang/test/SemaOpenCLCXX/address-space-templates.cl @@ -4,9 +4,7 @@ template struct S { T a; // expected-error{{field may not be qualified with an address space}} T f1(); // expected-error{{function type may not be qualified with an address space}} - // FIXME: Should only get the error message once. - void f2(T); // expected-error{{parameter may not be qualified with an address space}} expected-error{{parameter may not be qualified with an address space}} - + void f2(T); // expected-error{{parameter may not be qualified with an address space}} }; template diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 4de7364..e9bc393 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -8370,7 +8370,7 @@ unsigned clang_CXXMethod_isConst(CXCursor C) { const Decl *D = cxcursor::getCursorDecl(C); const CXXMethodDecl *Method = D ? dyn_cast_or_null(D->getAsFunction()) : nullptr; - return (Method && Method->getTypeQualifiers().hasConst()) ? 1 : 0; + return (Method && (Method->getTypeQualifiers() & Qualifiers::Const)) ? 1 : 0; } unsigned clang_CXXMethod_isDefaulted(CXCursor C) { -- 2.7.4