forked from OSchip/llvm-project
[OpenCL] Add generic AS to 'this' pointer
Address spaces are cast into generic before invoking the constructor. Added support for a trailing Qualifiers object in FunctionProtoType. Differential Revision: https://reviews.llvm.org/D54862 llvm-svn: 348927
This commit is contained in:
parent
f6c898e12f
commit
78de84719b
|
@ -510,7 +510,7 @@ struct CanProxyAdaptor<FunctionProtoType>
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
|
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
|
||||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals)
|
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getTypeQuals)
|
||||||
|
|
||||||
using param_type_iterator =
|
using param_type_iterator =
|
||||||
CanTypeIterator<FunctionProtoType::param_type_iterator>;
|
CanTypeIterator<FunctionProtoType::param_type_iterator>;
|
||||||
|
|
|
@ -2182,7 +2182,10 @@ public:
|
||||||
/// 'this' type.
|
/// 'this' type.
|
||||||
QualType getThisType(ASTContext &C) const;
|
QualType getThisType(ASTContext &C) const;
|
||||||
|
|
||||||
unsigned getTypeQualifiers() const {
|
static QualType getThisType(const FunctionProtoType *FPT,
|
||||||
|
const CXXRecordDecl *Decl);
|
||||||
|
|
||||||
|
Qualifiers getTypeQualifiers() const {
|
||||||
return getType()->getAs<FunctionProtoType>()->getTypeQuals();
|
return getType()->getAs<FunctionProtoType>()->getTypeQuals();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -256,28 +256,24 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasConst() const { return Mask & Const; }
|
bool hasConst() const { return Mask & Const; }
|
||||||
void setConst(bool flag) {
|
bool hasOnlyConst() const { return Mask == Const; }
|
||||||
Mask = (Mask & ~Const) | (flag ? Const : 0);
|
|
||||||
}
|
|
||||||
void removeConst() { Mask &= ~Const; }
|
void removeConst() { Mask &= ~Const; }
|
||||||
void addConst() { Mask |= Const; }
|
void addConst() { Mask |= Const; }
|
||||||
|
|
||||||
bool hasVolatile() const { return Mask & Volatile; }
|
bool hasVolatile() const { return Mask & Volatile; }
|
||||||
void setVolatile(bool flag) {
|
bool hasOnlyVolatile() const { return Mask == Volatile; }
|
||||||
Mask = (Mask & ~Volatile) | (flag ? Volatile : 0);
|
|
||||||
}
|
|
||||||
void removeVolatile() { Mask &= ~Volatile; }
|
void removeVolatile() { Mask &= ~Volatile; }
|
||||||
void addVolatile() { Mask |= Volatile; }
|
void addVolatile() { Mask |= Volatile; }
|
||||||
|
|
||||||
bool hasRestrict() const { return Mask & Restrict; }
|
bool hasRestrict() const { return Mask & Restrict; }
|
||||||
void setRestrict(bool flag) {
|
bool hasOnlyRestrict() const { return Mask == Restrict; }
|
||||||
Mask = (Mask & ~Restrict) | (flag ? Restrict : 0);
|
|
||||||
}
|
|
||||||
void removeRestrict() { Mask &= ~Restrict; }
|
void removeRestrict() { Mask &= ~Restrict; }
|
||||||
void addRestrict() { Mask |= Restrict; }
|
void addRestrict() { Mask |= Restrict; }
|
||||||
|
|
||||||
bool hasCVRQualifiers() const { return getCVRQualifiers(); }
|
bool hasCVRQualifiers() const { return getCVRQualifiers(); }
|
||||||
unsigned getCVRQualifiers() const { return Mask & CVRMask; }
|
unsigned getCVRQualifiers() const { return Mask & CVRMask; }
|
||||||
|
unsigned getCVRUQualifiers() const { return Mask & (CVRMask | UMask); }
|
||||||
|
|
||||||
void setCVRQualifiers(unsigned mask) {
|
void setCVRQualifiers(unsigned mask) {
|
||||||
assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
|
assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
|
||||||
Mask = (Mask & ~CVRMask) | mask;
|
Mask = (Mask & ~CVRMask) | mask;
|
||||||
|
@ -1526,7 +1522,9 @@ protected:
|
||||||
///
|
///
|
||||||
/// C++ 8.3.5p4: The return type, the parameter type list and the
|
/// C++ 8.3.5p4: The return type, the parameter type list and the
|
||||||
/// cv-qualifier-seq, [...], are part of the function type.
|
/// cv-qualifier-seq, [...], are part of the function type.
|
||||||
unsigned TypeQuals : 4;
|
unsigned FastTypeQuals : Qualifiers::FastWidth;
|
||||||
|
/// Whether this function has extended Qualifiers.
|
||||||
|
unsigned HasExtQuals : 1;
|
||||||
|
|
||||||
/// The number of parameters this function has, not counting '...'.
|
/// The number of parameters this function has, not counting '...'.
|
||||||
/// According to [implimits] 8 bits should be enough here but this is
|
/// According to [implimits] 8 bits should be enough here but this is
|
||||||
|
@ -3611,7 +3609,9 @@ protected:
|
||||||
FunctionTypeBits.ExtInfo = Info.Bits;
|
FunctionTypeBits.ExtInfo = Info.Bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; }
|
Qualifiers getFastTypeQuals() const {
|
||||||
|
return Qualifiers::fromFastMask(FunctionTypeBits.FastTypeQuals);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QualType getReturnType() const { return ResultType; }
|
QualType getReturnType() const { return ResultType; }
|
||||||
|
@ -3626,9 +3626,14 @@ public:
|
||||||
|
|
||||||
CallingConv getCallConv() const { return getExtInfo().getCC(); }
|
CallingConv getCallConv() const { return getExtInfo().getCC(); }
|
||||||
ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
|
ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
|
||||||
bool isConst() const { return getTypeQuals() & Qualifiers::Const; }
|
|
||||||
bool isVolatile() const { return getTypeQuals() & Qualifiers::Volatile; }
|
static_assert((~Qualifiers::FastMask & Qualifiers::CVRMask) == 0,
|
||||||
bool isRestrict() const { return getTypeQuals() & Qualifiers::Restrict; }
|
"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(); }
|
||||||
|
|
||||||
/// Determine the type of an expression that calls a function of
|
/// Determine the type of an expression that calls a function of
|
||||||
/// this type.
|
/// this type.
|
||||||
|
@ -3689,7 +3694,7 @@ class FunctionProtoType final
|
||||||
private llvm::TrailingObjects<
|
private llvm::TrailingObjects<
|
||||||
FunctionProtoType, QualType, FunctionType::FunctionTypeExtraBitfields,
|
FunctionProtoType, QualType, FunctionType::FunctionTypeExtraBitfields,
|
||||||
FunctionType::ExceptionType, Expr *, FunctionDecl *,
|
FunctionType::ExceptionType, Expr *, FunctionDecl *,
|
||||||
FunctionType::ExtParameterInfo> {
|
FunctionType::ExtParameterInfo, Qualifiers> {
|
||||||
friend class ASTContext; // ASTContext creates these.
|
friend class ASTContext; // ASTContext creates these.
|
||||||
friend TrailingObjects;
|
friend TrailingObjects;
|
||||||
|
|
||||||
|
@ -3717,6 +3722,10 @@ class FunctionProtoType final
|
||||||
// an ExtParameterInfo for each of the parameters. Present if and
|
// an ExtParameterInfo for each of the parameters. Present if and
|
||||||
// only if hasExtParameterInfos() is true.
|
// 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
|
// The optional FunctionTypeExtraBitfields has to be before the data
|
||||||
// related to the exception specification since it contains the number
|
// related to the exception specification since it contains the number
|
||||||
// of exception types.
|
// of exception types.
|
||||||
|
@ -3763,7 +3772,7 @@ public:
|
||||||
FunctionType::ExtInfo ExtInfo;
|
FunctionType::ExtInfo ExtInfo;
|
||||||
bool Variadic : 1;
|
bool Variadic : 1;
|
||||||
bool HasTrailingReturn : 1;
|
bool HasTrailingReturn : 1;
|
||||||
unsigned char TypeQuals = 0;
|
Qualifiers TypeQuals;
|
||||||
RefQualifierKind RefQualifier = RQ_None;
|
RefQualifierKind RefQualifier = RQ_None;
|
||||||
ExceptionSpecInfo ExceptionSpec;
|
ExceptionSpecInfo ExceptionSpec;
|
||||||
const ExtParameterInfo *ExtParameterInfos = nullptr;
|
const ExtParameterInfo *ExtParameterInfos = nullptr;
|
||||||
|
@ -3875,6 +3884,10 @@ private:
|
||||||
return hasExtraBitfields(getExceptionSpecType());
|
return hasExtraBitfields(getExceptionSpecType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasExtQualifiers() const {
|
||||||
|
return FunctionTypeBits.HasExtQuals;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
unsigned getNumParams() const { return FunctionTypeBits.NumParams; }
|
unsigned getNumParams() const { return FunctionTypeBits.NumParams; }
|
||||||
|
|
||||||
|
@ -3893,7 +3906,7 @@ public:
|
||||||
EPI.Variadic = isVariadic();
|
EPI.Variadic = isVariadic();
|
||||||
EPI.HasTrailingReturn = hasTrailingReturn();
|
EPI.HasTrailingReturn = hasTrailingReturn();
|
||||||
EPI.ExceptionSpec.Type = getExceptionSpecType();
|
EPI.ExceptionSpec.Type = getExceptionSpecType();
|
||||||
EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals());
|
EPI.TypeQuals = getTypeQuals();
|
||||||
EPI.RefQualifier = getRefQualifier();
|
EPI.RefQualifier = getRefQualifier();
|
||||||
if (EPI.ExceptionSpec.Type == EST_Dynamic) {
|
if (EPI.ExceptionSpec.Type == EST_Dynamic) {
|
||||||
EPI.ExceptionSpec.Exceptions = exceptions();
|
EPI.ExceptionSpec.Exceptions = exceptions();
|
||||||
|
@ -4003,7 +4016,12 @@ public:
|
||||||
/// Whether this function prototype has a trailing return type.
|
/// Whether this function prototype has a trailing return type.
|
||||||
bool hasTrailingReturn() const { return FunctionTypeBits.HasTrailingReturn; }
|
bool hasTrailingReturn() const { return FunctionTypeBits.HasTrailingReturn; }
|
||||||
|
|
||||||
unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
|
Qualifiers getTypeQuals() const {
|
||||||
|
if (hasExtQualifiers())
|
||||||
|
return *getTrailingObjects<Qualifiers>();
|
||||||
|
else
|
||||||
|
return getFastTypeQuals();
|
||||||
|
}
|
||||||
|
|
||||||
/// Retrieve the ref-qualifier associated with this function type.
|
/// Retrieve the ref-qualifier associated with this function type.
|
||||||
RefQualifierKind getRefQualifier() const {
|
RefQualifierKind getRefQualifier() const {
|
||||||
|
|
|
@ -5115,7 +5115,7 @@ public:
|
||||||
/// using the given declaration (which is either a class template or a
|
/// using the given declaration (which is either a class template or a
|
||||||
/// class) along with the given qualifiers.
|
/// class) along with the given qualifiers.
|
||||||
/// along with the qualifiers placed on '*this'.
|
/// along with the qualifiers placed on '*this'.
|
||||||
CXXThisScopeRAII(Sema &S, Decl *ContextDecl, unsigned CXXThisTypeQuals,
|
CXXThisScopeRAII(Sema &S, Decl *ContextDecl, Qualifiers CXXThisTypeQuals,
|
||||||
bool Enabled = true);
|
bool Enabled = true);
|
||||||
|
|
||||||
~CXXThisScopeRAII();
|
~CXXThisScopeRAII();
|
||||||
|
@ -7752,7 +7752,7 @@ public:
|
||||||
SourceLocation Loc,
|
SourceLocation Loc,
|
||||||
DeclarationName Entity,
|
DeclarationName Entity,
|
||||||
CXXRecordDecl *ThisContext,
|
CXXRecordDecl *ThisContext,
|
||||||
unsigned ThisTypeQuals);
|
Qualifiers ThisTypeQuals);
|
||||||
void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
|
void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
|
||||||
const MultiLevelTemplateArgumentList &Args);
|
const MultiLevelTemplateArgumentList &Args);
|
||||||
bool SubstExceptionSpec(SourceLocation Loc,
|
bool SubstExceptionSpec(SourceLocation Loc,
|
||||||
|
|
|
@ -3768,10 +3768,11 @@ QualType ASTContext::getFunctionTypeInternal(
|
||||||
size_t Size = FunctionProtoType::totalSizeToAlloc<
|
size_t Size = FunctionProtoType::totalSizeToAlloc<
|
||||||
QualType, FunctionType::FunctionTypeExtraBitfields,
|
QualType, FunctionType::FunctionTypeExtraBitfields,
|
||||||
FunctionType::ExceptionType, Expr *, FunctionDecl *,
|
FunctionType::ExceptionType, Expr *, FunctionDecl *,
|
||||||
FunctionProtoType::ExtParameterInfo>(
|
FunctionProtoType::ExtParameterInfo, Qualifiers>(
|
||||||
NumArgs, FunctionProtoType::hasExtraBitfields(EPI.ExceptionSpec.Type),
|
NumArgs, FunctionProtoType::hasExtraBitfields(EPI.ExceptionSpec.Type),
|
||||||
ESH.NumExceptionType, ESH.NumExprPtr, ESH.NumFunctionDeclPtr,
|
ESH.NumExceptionType, ESH.NumExprPtr, ESH.NumFunctionDeclPtr,
|
||||||
EPI.ExtParameterInfos ? NumArgs : 0);
|
EPI.ExtParameterInfos ? NumArgs : 0,
|
||||||
|
EPI.TypeQuals.hasNonFastQualifiers() ? 1 : 0);
|
||||||
|
|
||||||
auto *FTP = (FunctionProtoType *)Allocate(Size, TypeAlignment);
|
auto *FTP = (FunctionProtoType *)Allocate(Size, TypeAlignment);
|
||||||
FunctionProtoType::ExtProtoInfo newEPI = EPI;
|
FunctionProtoType::ExtProtoInfo newEPI = EPI;
|
||||||
|
|
|
@ -199,9 +199,10 @@ namespace {
|
||||||
void VisitFunctionProtoType(const FunctionProtoType *T) {
|
void VisitFunctionProtoType(const FunctionProtoType *T) {
|
||||||
auto EPI = T->getExtProtoInfo();
|
auto EPI = T->getExtProtoInfo();
|
||||||
if (EPI.HasTrailingReturn) OS << " trailing_return";
|
if (EPI.HasTrailingReturn) OS << " trailing_return";
|
||||||
if (T->isConst()) OS << " const";
|
|
||||||
if (T->isVolatile()) OS << " volatile";
|
if (!T->getTypeQuals().empty())
|
||||||
if (T->isRestrict()) OS << " restrict";
|
OS << " " << T->getTypeQuals().getAsString();
|
||||||
|
|
||||||
switch (EPI.RefQualifier) {
|
switch (EPI.RefQualifier) {
|
||||||
case RQ_None: break;
|
case RQ_None: break;
|
||||||
case RQ_LValue: OS << " &"; break;
|
case RQ_LValue: OS << " &"; break;
|
||||||
|
|
|
@ -2173,19 +2173,24 @@ CXXMethodDecl::overridden_methods() const {
|
||||||
return getASTContext().overridden_methods(this);
|
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 {
|
QualType CXXMethodDecl::getThisType(ASTContext &C) const {
|
||||||
// C++ 9.3.2p1: The type of this in a member function of a class X is X*.
|
// 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 const, the type of this is const X*,
|
||||||
// if the member function is declared volatile, the type of this is
|
// if the member function is declared volatile, the type of this is
|
||||||
// volatile X*, and if the member function is declared const volatile,
|
// volatile X*, and if the member function is declared const volatile,
|
||||||
// the type of this is const volatile X*.
|
// the type of this is const volatile X*.
|
||||||
|
|
||||||
assert(isInstance() && "No 'this' for static methods!");
|
assert(isInstance() && "No 'this' for static methods!");
|
||||||
|
|
||||||
QualType ClassTy = C.getTypeDeclType(getParent());
|
return CXXMethodDecl::getThisType(getType()->getAs<FunctionProtoType>(),
|
||||||
ClassTy = C.getQualifiedType(ClassTy,
|
getParent());
|
||||||
Qualifiers::fromCVRUMask(getTypeQualifiers()));
|
|
||||||
return C.getPointerType(ClassTy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CXXMethodDecl::hasInlineBody() const {
|
bool CXXMethodDecl::hasInlineBody() const {
|
||||||
|
|
|
@ -1503,8 +1503,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
|
||||||
|
|
||||||
Out << 'N';
|
Out << 'N';
|
||||||
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) {
|
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) {
|
||||||
Qualifiers MethodQuals =
|
Qualifiers MethodQuals = Method->getTypeQualifiers();
|
||||||
Qualifiers::fromCVRUMask(Method->getTypeQualifiers());
|
|
||||||
// We do not consider restrict a distinguishing attribute for overloading
|
// We do not consider restrict a distinguishing attribute for overloading
|
||||||
// purposes so we must not mangle it.
|
// purposes so we must not mangle it.
|
||||||
MethodQuals.removeRestrict();
|
MethodQuals.removeRestrict();
|
||||||
|
@ -2725,7 +2724,7 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) {
|
||||||
|
|
||||||
// Mangle CV-qualifiers, if present. These are 'this' qualifiers,
|
// Mangle CV-qualifiers, if present. These are 'this' qualifiers,
|
||||||
// e.g. "const" in "int (A::*)() const".
|
// e.g. "const" in "int (A::*)() const".
|
||||||
mangleQualifiers(Qualifiers::fromCVRUMask(T->getTypeQuals()));
|
mangleQualifiers(T->getTypeQuals());
|
||||||
|
|
||||||
// Mangle instantiation-dependent exception-specification, if present,
|
// Mangle instantiation-dependent exception-specification, if present,
|
||||||
// per cxx-abi-dev proposal on 2016-10-11.
|
// per cxx-abi-dev proposal on 2016-10-11.
|
||||||
|
|
|
@ -2093,7 +2093,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
|
||||||
// If this is a C++ instance method, mangle the CVR qualifiers for the
|
// If this is a C++ instance method, mangle the CVR qualifiers for the
|
||||||
// this pointer.
|
// this pointer.
|
||||||
if (HasThisQuals) {
|
if (HasThisQuals) {
|
||||||
Qualifiers Quals = Qualifiers::fromCVRUMask(Proto->getTypeQuals());
|
Qualifiers Quals = Proto->getTypeQuals();
|
||||||
manglePointerExtQualifiers(Quals, /*PointeeType=*/QualType());
|
manglePointerExtQualifiers(Quals, /*PointeeType=*/QualType());
|
||||||
mangleRefQualifier(Proto->getRefQualifier());
|
mangleRefQualifier(Proto->getRefQualifier());
|
||||||
mangleQualifiers(Quals, /*IsMember=*/false);
|
mangleQualifiers(Quals, /*IsMember=*/false);
|
||||||
|
|
|
@ -2851,7 +2851,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
|
||||||
result->isInstantiationDependentType(),
|
result->isInstantiationDependentType(),
|
||||||
result->isVariablyModifiedType(),
|
result->isVariablyModifiedType(),
|
||||||
result->containsUnexpandedParameterPack(), epi.ExtInfo) {
|
result->containsUnexpandedParameterPack(), epi.ExtInfo) {
|
||||||
FunctionTypeBits.TypeQuals = epi.TypeQuals;
|
FunctionTypeBits.FastTypeQuals = epi.TypeQuals.getFastQualifiers();
|
||||||
FunctionTypeBits.RefQualifier = epi.RefQualifier;
|
FunctionTypeBits.RefQualifier = epi.RefQualifier;
|
||||||
FunctionTypeBits.NumParams = params.size();
|
FunctionTypeBits.NumParams = params.size();
|
||||||
assert(getNumParams() == params.size() && "NumParams overflow!");
|
assert(getNumParams() == params.size() && "NumParams overflow!");
|
||||||
|
@ -2950,6 +2950,13 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
|
||||||
for (unsigned i = 0; i != getNumParams(); ++i)
|
for (unsigned i = 0; i != getNumParams(); ++i)
|
||||||
extParamInfos[i] = epi.ExtParameterInfos[i];
|
extParamInfos[i] = epi.ExtParameterInfos[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (epi.TypeQuals.hasNonFastQualifiers()) {
|
||||||
|
FunctionTypeBits.HasExtQuals = 1;
|
||||||
|
*getTrailingObjects<Qualifiers>() = epi.TypeQuals;
|
||||||
|
} else {
|
||||||
|
FunctionTypeBits.HasExtQuals = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FunctionProtoType::hasDependentExceptionSpec() const {
|
bool FunctionProtoType::hasDependentExceptionSpec() const {
|
||||||
|
@ -3041,14 +3048,13 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
|
||||||
// shortcut, use one AddInteger call instead of four for the next four
|
// shortcut, use one AddInteger call instead of four for the next four
|
||||||
// fields.
|
// fields.
|
||||||
assert(!(unsigned(epi.Variadic) & ~1) &&
|
assert(!(unsigned(epi.Variadic) & ~1) &&
|
||||||
!(unsigned(epi.TypeQuals) & ~255) &&
|
|
||||||
!(unsigned(epi.RefQualifier) & ~3) &&
|
!(unsigned(epi.RefQualifier) & ~3) &&
|
||||||
!(unsigned(epi.ExceptionSpec.Type) & ~15) &&
|
!(unsigned(epi.ExceptionSpec.Type) & ~15) &&
|
||||||
"Values larger than expected.");
|
"Values larger than expected.");
|
||||||
ID.AddInteger(unsigned(epi.Variadic) +
|
ID.AddInteger(unsigned(epi.Variadic) +
|
||||||
(epi.TypeQuals << 1) +
|
(epi.RefQualifier << 1) +
|
||||||
(epi.RefQualifier << 9) +
|
(epi.ExceptionSpec.Type << 3));
|
||||||
(epi.ExceptionSpec.Type << 11));
|
ID.Add(epi.TypeQuals);
|
||||||
if (epi.ExceptionSpec.Type == EST_Dynamic) {
|
if (epi.ExceptionSpec.Type == EST_Dynamic) {
|
||||||
for (QualType Ex : epi.ExceptionSpec.Exceptions)
|
for (QualType Ex : epi.ExceptionSpec.Exceptions)
|
||||||
ID.AddPointer(Ex.getAsOpaquePtr());
|
ID.AddPointer(Ex.getAsOpaquePtr());
|
||||||
|
|
|
@ -801,10 +801,8 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
|
||||||
|
|
||||||
printFunctionAfter(Info, OS);
|
printFunctionAfter(Info, OS);
|
||||||
|
|
||||||
if (unsigned quals = T->getTypeQuals()) {
|
if (!T->getTypeQuals().empty())
|
||||||
OS << ' ';
|
OS << " " << T->getTypeQuals().getAsString();
|
||||||
AppendTypeQualList(OS, quals, Policy.Restrict);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (T->getRefQualifier()) {
|
switch (T->getRefQualifier()) {
|
||||||
case RQ_None:
|
case RQ_None:
|
||||||
|
|
|
@ -68,11 +68,13 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Derives the 'this' type for codegen purposes, i.e. ignoring method
|
/// Derives the 'this' type for codegen purposes, i.e. ignoring method CVR
|
||||||
/// qualification.
|
/// qualification.
|
||||||
/// FIXME: address space qualification?
|
static CanQualType GetThisType(ASTContext &Context, const CXXRecordDecl *RD,
|
||||||
static CanQualType GetThisType(ASTContext &Context, const CXXRecordDecl *RD) {
|
const CXXMethodDecl *MD) {
|
||||||
QualType RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal();
|
QualType RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal();
|
||||||
|
if (MD)
|
||||||
|
RecTy = Context.getAddrSpaceQualType(RecTy, MD->getType().getAddressSpace());
|
||||||
return Context.getPointerType(CanQualType::CreateUnsafe(RecTy));
|
return Context.getPointerType(CanQualType::CreateUnsafe(RecTy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +252,7 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
|
||||||
|
|
||||||
// Add the 'this' pointer.
|
// Add the 'this' pointer.
|
||||||
if (RD)
|
if (RD)
|
||||||
argTypes.push_back(GetThisType(Context, RD));
|
argTypes.push_back(GetThisType(Context, RD, MD));
|
||||||
else
|
else
|
||||||
argTypes.push_back(Context.VoidPtrTy);
|
argTypes.push_back(Context.VoidPtrTy);
|
||||||
|
|
||||||
|
@ -306,7 +308,7 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
|
||||||
|
|
||||||
SmallVector<CanQualType, 16> argTypes;
|
SmallVector<CanQualType, 16> argTypes;
|
||||||
SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
|
SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
|
||||||
argTypes.push_back(GetThisType(Context, MD->getParent()));
|
argTypes.push_back(GetThisType(Context, MD->getParent(), MD));
|
||||||
|
|
||||||
bool PassParams = true;
|
bool PassParams = true;
|
||||||
|
|
||||||
|
@ -533,7 +535,7 @@ const CGFunctionInfo &
|
||||||
CodeGenTypes::arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD) {
|
CodeGenTypes::arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD) {
|
||||||
assert(MD->isVirtual() && "only methods have thunks");
|
assert(MD->isVirtual() && "only methods have thunks");
|
||||||
CanQual<FunctionProtoType> FTP = GetFormalType(MD);
|
CanQual<FunctionProtoType> FTP = GetFormalType(MD);
|
||||||
CanQualType ArgTys[] = { GetThisType(Context, MD->getParent()) };
|
CanQualType ArgTys[] = { GetThisType(Context, MD->getParent(), MD) };
|
||||||
return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false,
|
return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false,
|
||||||
/*chainCall=*/false, ArgTys,
|
/*chainCall=*/false, ArgTys,
|
||||||
FTP->getExtInfo(), {}, RequiredArgs(1));
|
FTP->getExtInfo(), {}, RequiredArgs(1));
|
||||||
|
@ -547,7 +549,7 @@ CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD,
|
||||||
CanQual<FunctionProtoType> FTP = GetFormalType(CD);
|
CanQual<FunctionProtoType> FTP = GetFormalType(CD);
|
||||||
SmallVector<CanQualType, 2> ArgTys;
|
SmallVector<CanQualType, 2> ArgTys;
|
||||||
const CXXRecordDecl *RD = CD->getParent();
|
const CXXRecordDecl *RD = CD->getParent();
|
||||||
ArgTys.push_back(GetThisType(Context, RD));
|
ArgTys.push_back(GetThisType(Context, RD, CD));
|
||||||
if (CT == Ctor_CopyingClosure)
|
if (CT == Ctor_CopyingClosure)
|
||||||
ArgTys.push_back(*FTP->param_type_begin());
|
ArgTys.push_back(*FTP->param_type_begin());
|
||||||
if (RD->getNumVBases() > 0)
|
if (RD->getNumVBases() > 0)
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "CGDebugInfo.h"
|
#include "CGDebugInfo.h"
|
||||||
#include "CGRecordLayout.h"
|
#include "CGRecordLayout.h"
|
||||||
#include "CodeGenFunction.h"
|
#include "CodeGenFunction.h"
|
||||||
|
#include "TargetInfo.h"
|
||||||
#include "clang/AST/CXXInheritance.h"
|
#include "clang/AST/CXXInheritance.h"
|
||||||
#include "clang/AST/DeclTemplate.h"
|
#include "clang/AST/DeclTemplate.h"
|
||||||
#include "clang/AST/EvaluatedExprVisitor.h"
|
#include "clang/AST/EvaluatedExprVisitor.h"
|
||||||
|
@ -2012,8 +2013,19 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
|
||||||
bool NewPointerIsChecked) {
|
bool NewPointerIsChecked) {
|
||||||
CallArgList Args;
|
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.
|
// Push the this ptr.
|
||||||
Args.add(RValue::get(This.getPointer()), D->getThisType(getContext()));
|
Args.add(RValue::get(ThisPtr), D->getThisType(getContext()));
|
||||||
|
|
||||||
// If this is a trivial constructor, emit a memcpy now before we lose
|
// If this is a trivial constructor, emit a memcpy now before we lose
|
||||||
// the alignment information on the argument.
|
// the alignment information on the argument.
|
||||||
|
|
|
@ -2617,8 +2617,8 @@ llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty,
|
||||||
const FunctionProtoType *FPT =
|
const FunctionProtoType *FPT =
|
||||||
Ty->getPointeeType()->getAs<FunctionProtoType>();
|
Ty->getPointeeType()->getAs<FunctionProtoType>();
|
||||||
return DBuilder.createMemberPointerType(
|
return DBuilder.createMemberPointerType(
|
||||||
getOrCreateInstanceMethodType(CGM.getContext().getPointerType(QualType(
|
getOrCreateInstanceMethodType(
|
||||||
Ty->getClass(), FPT->getTypeQuals())),
|
CXXMethodDecl::getThisType(FPT, Ty->getMostRecentCXXRecordDecl()),
|
||||||
FPT, U),
|
FPT, U),
|
||||||
ClassType, Size, /*Align=*/0, Flags);
|
ClassType, Size, /*Align=*/0, Flags);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,10 @@ using namespace CodeGen;
|
||||||
|
|
||||||
static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
|
static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
|
||||||
ConstantAddress DeclPtr) {
|
ConstantAddress DeclPtr) {
|
||||||
assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
|
assert(
|
||||||
|
(D.hasGlobalStorage() ||
|
||||||
|
(D.hasLocalStorage() && CGF.getContext().getLangOpts().OpenCLCPlusPlus)) &&
|
||||||
|
"VarDecl must have global or local (in the case of OpenCL) storage!");
|
||||||
assert(!D.getType()->isReferenceType() &&
|
assert(!D.getType()->isReferenceType() &&
|
||||||
"Should not call EmitDeclInit on a reference!");
|
"Should not call EmitDeclInit on a reference!");
|
||||||
|
|
||||||
|
|
|
@ -3948,7 +3948,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
|
||||||
LValue RefLVal = MakeAddrLValue(addr, FieldType, FieldBaseInfo,
|
LValue RefLVal = MakeAddrLValue(addr, FieldType, FieldBaseInfo,
|
||||||
FieldTBAAInfo);
|
FieldTBAAInfo);
|
||||||
if (RecordCVR & Qualifiers::Volatile)
|
if (RecordCVR & Qualifiers::Volatile)
|
||||||
RefLVal.getQuals().setVolatile(true);
|
RefLVal.getQuals().addVolatile();
|
||||||
addr = EmitLoadOfReference(RefLVal, &FieldBaseInfo, &FieldTBAAInfo);
|
addr = EmitLoadOfReference(RefLVal, &FieldBaseInfo, &FieldTBAAInfo);
|
||||||
|
|
||||||
// Qualifiers on the struct don't apply to the referencee.
|
// Qualifiers on the struct don't apply to the referencee.
|
||||||
|
|
|
@ -562,7 +562,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void setVolatile(bool flag) {
|
void setVolatile(bool flag) {
|
||||||
Quals.setVolatile(flag);
|
if (flag)
|
||||||
|
Quals.addVolatile();
|
||||||
|
else
|
||||||
|
Quals.removeVolatile();
|
||||||
}
|
}
|
||||||
|
|
||||||
Qualifiers::ObjCLifetime getObjCLifetime() const {
|
Qualifiers::ObjCLifetime getObjCLifetime() const {
|
||||||
|
|
|
@ -270,7 +270,8 @@ void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
|
||||||
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
|
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
|
||||||
if (MD->isStatic())
|
if (MD->isStatic())
|
||||||
Out << 'S';
|
Out << 'S';
|
||||||
if (unsigned quals = MD->getTypeQualifiers())
|
// FIXME: OpenCL: Need to consider address spaces
|
||||||
|
if (unsigned quals = MD->getTypeQualifiers().getCVRUQualifiers())
|
||||||
Out << (char)('0' + quals);
|
Out << (char)('0' + quals);
|
||||||
switch (MD->getRefQualifier()) {
|
switch (MD->getRefQualifier()) {
|
||||||
case RQ_None: break;
|
case RQ_None: break;
|
||||||
|
|
|
@ -595,7 +595,7 @@ void Parser::ParseLexedMemberInitializers(ParsingClass &Class) {
|
||||||
// to X" within the optional brace-or-equal-initializer. It shall not
|
// to X" within the optional brace-or-equal-initializer. It shall not
|
||||||
// appear elsewhere in the member-declarator.
|
// appear elsewhere in the member-declarator.
|
||||||
Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate,
|
Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate,
|
||||||
/*TypeQuals=*/(unsigned)0);
|
Qualifiers());
|
||||||
|
|
||||||
for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
|
for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
|
||||||
Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers();
|
Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers();
|
||||||
|
|
|
@ -1427,7 +1427,7 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
|
||||||
RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
|
RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
|
||||||
|
|
||||||
// Allow 'this' within late-parsed attributes.
|
// Allow 'this' within late-parsed attributes.
|
||||||
Sema::CXXThisScopeRAII ThisScope(Actions, RD, /*TypeQuals=*/0,
|
Sema::CXXThisScopeRAII ThisScope(Actions, RD, Qualifiers(),
|
||||||
ND && ND->isCXXInstanceMember());
|
ND && ND->isCXXInstanceMember());
|
||||||
|
|
||||||
if (LA.Decls.size() == 1) {
|
if (LA.Decls.size() == 1) {
|
||||||
|
@ -6162,12 +6162,13 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
|
||||||
: D.getContext() == DeclaratorContext::FileContext &&
|
: D.getContext() == DeclaratorContext::FileContext &&
|
||||||
D.getCXXScopeSpec().isValid() &&
|
D.getCXXScopeSpec().isValid() &&
|
||||||
Actions.CurContext->isRecord());
|
Actions.CurContext->isRecord());
|
||||||
Sema::CXXThisScopeRAII ThisScope(Actions,
|
|
||||||
dyn_cast<CXXRecordDecl>(Actions.CurContext),
|
Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers());
|
||||||
DS.getTypeQualifiers() |
|
if (D.getDeclSpec().isConstexprSpecified() && !getLangOpts().CPlusPlus14)
|
||||||
(D.getDeclSpec().isConstexprSpecified() &&
|
Q.addConst();
|
||||||
!getLangOpts().CPlusPlus14
|
|
||||||
? Qualifiers::Const : 0),
|
Sema::CXXThisScopeRAII ThisScope(
|
||||||
|
Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), Q,
|
||||||
IsCXX11MemberFunction);
|
IsCXX11MemberFunction);
|
||||||
|
|
||||||
// Parse exception-specification[opt].
|
// Parse exception-specification[opt].
|
||||||
|
|
|
@ -495,7 +495,7 @@ public:
|
||||||
Sema &Actions = P.getActions();
|
Sema &Actions = P.getActions();
|
||||||
|
|
||||||
// Allow 'this' within late-parsed attributes.
|
// Allow 'this' within late-parsed attributes.
|
||||||
ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0,
|
ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
|
||||||
ND && ND->isCXXInstanceMember());
|
ND && ND->isCXXInstanceMember());
|
||||||
|
|
||||||
// If the Decl is templatized, add template parameters to scope.
|
// If the Decl is templatized, add template parameters to scope.
|
||||||
|
|
|
@ -1028,8 +1028,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
|
||||||
if (HasObjectTypeQualifiers)
|
if (HasObjectTypeQualifiers)
|
||||||
if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
|
if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
|
||||||
if (Method->isInstance()) {
|
if (Method->isInstance()) {
|
||||||
Qualifiers MethodQuals =
|
Qualifiers MethodQuals = Method->getTypeQualifiers();
|
||||||
Qualifiers::fromCVRMask(Method->getTypeQualifiers());
|
|
||||||
if (ObjectTypeQualifiers == MethodQuals)
|
if (ObjectTypeQualifiers == MethodQuals)
|
||||||
R.Priority += CCD_ObjectQualifierMatch;
|
R.Priority += CCD_ObjectQualifierMatch;
|
||||||
else if (ObjectTypeQualifiers - MethodQuals) {
|
else if (ObjectTypeQualifiers - MethodQuals) {
|
||||||
|
@ -2743,17 +2742,17 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
|
||||||
// FIXME: Add ref-qualifier!
|
// FIXME: Add ref-qualifier!
|
||||||
|
|
||||||
// Handle single qualifiers without copying
|
// Handle single qualifiers without copying
|
||||||
if (Proto->getTypeQuals() == Qualifiers::Const) {
|
if (Proto->getTypeQuals().hasOnlyConst()) {
|
||||||
Result.AddInformativeChunk(" const");
|
Result.AddInformativeChunk(" const");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Proto->getTypeQuals() == Qualifiers::Volatile) {
|
if (Proto->getTypeQuals().hasOnlyVolatile()) {
|
||||||
Result.AddInformativeChunk(" volatile");
|
Result.AddInformativeChunk(" volatile");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Proto->getTypeQuals() == Qualifiers::Restrict) {
|
if (Proto->getTypeQuals().hasOnlyRestrict()) {
|
||||||
Result.AddInformativeChunk(" restrict");
|
Result.AddInformativeChunk(" restrict");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3738,8 +3737,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
|
||||||
// the member function to filter/prioritize the results list.
|
// the member function to filter/prioritize the results list.
|
||||||
if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext)) {
|
if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext)) {
|
||||||
if (CurMethod->isInstance()) {
|
if (CurMethod->isInstance()) {
|
||||||
Results.setObjectTypeQualifiers(
|
Results.setObjectTypeQualifiers(CurMethod->getTypeQualifiers());
|
||||||
Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3192,7 +3192,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
|
||||||
if (RequiresAdjustment) {
|
if (RequiresAdjustment) {
|
||||||
const FunctionType *AdjustedType = New->getType()->getAs<FunctionType>();
|
const FunctionType *AdjustedType = New->getType()->getAs<FunctionType>();
|
||||||
AdjustedType = Context.adjustFunctionType(AdjustedType, NewTypeInfo);
|
AdjustedType = Context.adjustFunctionType(AdjustedType, NewTypeInfo);
|
||||||
New->setType(QualType(AdjustedType, 0));
|
|
||||||
|
QualType AdjustedQT = QualType(AdjustedType, 0);
|
||||||
|
LangAS AS = Old->getType().getAddressSpace();
|
||||||
|
AdjustedQT = Context.getAddrSpaceQualType(AdjustedQT, AS);
|
||||||
|
|
||||||
|
New->setType(AdjustedQT);
|
||||||
NewQType = Context.getCanonicalType(New->getType());
|
NewQType = Context.getCanonicalType(New->getType());
|
||||||
NewType = cast<FunctionType>(NewQType);
|
NewType = cast<FunctionType>(NewQType);
|
||||||
}
|
}
|
||||||
|
@ -10017,7 +10022,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
||||||
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
|
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
|
||||||
if (!getLangOpts().CPlusPlus14 && MD && MD->isConstexpr() &&
|
if (!getLangOpts().CPlusPlus14 && MD && MD->isConstexpr() &&
|
||||||
!MD->isStatic() && !isa<CXXConstructorDecl>(MD) &&
|
!MD->isStatic() && !isa<CXXConstructorDecl>(MD) &&
|
||||||
(MD->getTypeQualifiers() & Qualifiers::Const) == 0) {
|
!MD->getTypeQualifiers().hasConst()) {
|
||||||
CXXMethodDecl *OldMD = nullptr;
|
CXXMethodDecl *OldMD = nullptr;
|
||||||
if (OldDecl)
|
if (OldDecl)
|
||||||
OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl->getAsFunction());
|
OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl->getAsFunction());
|
||||||
|
@ -10025,7 +10030,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
||||||
const FunctionProtoType *FPT =
|
const FunctionProtoType *FPT =
|
||||||
MD->getType()->castAs<FunctionProtoType>();
|
MD->getType()->castAs<FunctionProtoType>();
|
||||||
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
|
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
|
||||||
EPI.TypeQuals |= Qualifiers::Const;
|
EPI.TypeQuals.addConst();
|
||||||
MD->setType(Context.getFunctionType(FPT->getReturnType(),
|
MD->setType(Context.getFunctionType(FPT->getReturnType(),
|
||||||
FPT->getParamTypes(), EPI));
|
FPT->getParamTypes(), EPI));
|
||||||
|
|
||||||
|
|
|
@ -8199,7 +8199,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
|
||||||
return R;
|
return R;
|
||||||
|
|
||||||
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
|
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
|
||||||
EPI.TypeQuals = 0;
|
EPI.TypeQuals = Qualifiers();
|
||||||
EPI.RefQualifier = RQ_None;
|
EPI.RefQualifier = RQ_None;
|
||||||
|
|
||||||
return Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI);
|
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>();
|
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
|
||||||
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
|
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
|
||||||
EPI.Variadic = false;
|
EPI.Variadic = false;
|
||||||
EPI.TypeQuals = 0;
|
EPI.TypeQuals = Qualifiers();
|
||||||
EPI.RefQualifier = RQ_None;
|
EPI.RefQualifier = RQ_None;
|
||||||
return Context.getFunctionType(Context.VoidTy, None, EPI);
|
return Context.getFunctionType(Context.VoidTy, None, EPI);
|
||||||
}
|
}
|
||||||
|
@ -11991,7 +11991,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
|
||||||
// Dereference "this".
|
// Dereference "this".
|
||||||
DerefBuilder DerefThis(This);
|
DerefBuilder DerefThis(This);
|
||||||
CastBuilder To(DerefThis,
|
CastBuilder To(DerefThis,
|
||||||
Context.getCVRQualifiedType(
|
Context.getQualifiedType(
|
||||||
BaseType, CopyAssignOperator->getTypeQualifiers()),
|
BaseType, CopyAssignOperator->getTypeQualifiers()),
|
||||||
VK_LValue, BasePath);
|
VK_LValue, BasePath);
|
||||||
|
|
||||||
|
@ -12358,7 +12358,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
|
||||||
|
|
||||||
// Implicitly cast "this" to the appropriately-qualified base type.
|
// Implicitly cast "this" to the appropriately-qualified base type.
|
||||||
CastBuilder To(DerefThis,
|
CastBuilder To(DerefThis,
|
||||||
Context.getCVRQualifiedType(
|
Context.getQualifiedType(
|
||||||
BaseType, MoveAssignOperator->getTypeQualifiers()),
|
BaseType, MoveAssignOperator->getTypeQualifiers()),
|
||||||
VK_LValue, BasePath);
|
VK_LValue, BasePath);
|
||||||
|
|
||||||
|
|
|
@ -13553,7 +13553,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
|
||||||
// Drop the parameters.
|
// Drop the parameters.
|
||||||
FunctionProtoType::ExtProtoInfo EPI;
|
FunctionProtoType::ExtProtoInfo EPI;
|
||||||
EPI.HasTrailingReturn = false;
|
EPI.HasTrailingReturn = false;
|
||||||
EPI.TypeQuals |= DeclSpec::TQ_const;
|
EPI.TypeQuals.addConst();
|
||||||
T = Context.getFunctionType(Context.DependentTy, None, EPI);
|
T = Context.getFunctionType(Context.DependentTy, None, EPI);
|
||||||
Sig = Context.getTrivialTypeSourceInfo(T);
|
Sig = Context.getTrivialTypeSourceInfo(T);
|
||||||
}
|
}
|
||||||
|
@ -13729,7 +13729,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
|
||||||
} else {
|
} else {
|
||||||
const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy);
|
const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy);
|
||||||
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
|
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
|
||||||
EPI.TypeQuals = 0; // FIXME: silently?
|
EPI.TypeQuals = Qualifiers();
|
||||||
EPI.ExtInfo = Ext;
|
EPI.ExtInfo = Ext;
|
||||||
BlockTy = Context.getFunctionType(RetTy, FPT->getParamTypes(), EPI);
|
BlockTy = Context.getFunctionType(RetTy, FPT->getParamTypes(), EPI);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1094,7 +1094,7 @@ QualType Sema::getCurrentThisType() {
|
||||||
|
|
||||||
Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
|
Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
|
||||||
Decl *ContextDecl,
|
Decl *ContextDecl,
|
||||||
unsigned CXXThisTypeQuals,
|
Qualifiers CXXThisTypeQuals,
|
||||||
bool Enabled)
|
bool Enabled)
|
||||||
: S(S), OldCXXThisTypeOverride(S.CXXThisTypeOverride), Enabled(false)
|
: S(S), OldCXXThisTypeOverride(S.CXXThisTypeOverride), Enabled(false)
|
||||||
{
|
{
|
||||||
|
@ -1107,11 +1107,10 @@ Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
|
||||||
else
|
else
|
||||||
Record = cast<CXXRecordDecl>(ContextDecl);
|
Record = cast<CXXRecordDecl>(ContextDecl);
|
||||||
|
|
||||||
// We care only for CVR qualifiers here, so cut everything else.
|
QualType T = S.Context.getRecordType(Record);
|
||||||
CXXThisTypeQuals &= Qualifiers::FastMask;
|
T = S.getASTContext().getQualifiedType(T, CXXThisTypeQuals);
|
||||||
S.CXXThisTypeOverride
|
|
||||||
= S.Context.getPointerType(
|
S.CXXThisTypeOverride = S.Context.getPointerType(T);
|
||||||
S.Context.getRecordType(Record).withCVRQualifiers(CXXThisTypeQuals));
|
|
||||||
|
|
||||||
this->Enabled = true;
|
this->Enabled = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -859,7 +859,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
|
||||||
FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention(
|
FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention(
|
||||||
/*IsVariadic=*/false, /*IsCXXMethod=*/true));
|
/*IsVariadic=*/false, /*IsCXXMethod=*/true));
|
||||||
EPI.HasTrailingReturn = true;
|
EPI.HasTrailingReturn = true;
|
||||||
EPI.TypeQuals |= DeclSpec::TQ_const;
|
EPI.TypeQuals.addConst();
|
||||||
// C++1y [expr.prim.lambda]:
|
// C++1y [expr.prim.lambda]:
|
||||||
// The lambda return type is 'auto', which is replaced by the
|
// The lambda return type is 'auto', which is replaced by the
|
||||||
// trailing-return type if provided and/or deduced from 'return'
|
// trailing-return type if provided and/or deduced from 'return'
|
||||||
|
@ -1198,7 +1198,7 @@ QualType Sema::getLambdaConversionFunctionResultType(
|
||||||
CallingConv CC = Context.getDefaultCallingConvention(
|
CallingConv CC = Context.getDefaultCallingConvention(
|
||||||
CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
|
CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
|
||||||
InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
|
InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
|
||||||
InvokerExtInfo.TypeQuals = 0;
|
InvokerExtInfo.TypeQuals = Qualifiers();
|
||||||
assert(InvokerExtInfo.RefQualifier == RQ_None &&
|
assert(InvokerExtInfo.RefQualifier == RQ_None &&
|
||||||
"Lambda's call operator should not have a reference qualifier");
|
"Lambda's call operator should not have a reference qualifier");
|
||||||
return Context.getFunctionType(CallOpProto->getReturnType(),
|
return Context.getFunctionType(CallOpProto->getReturnType(),
|
||||||
|
@ -1229,7 +1229,8 @@ static void addFunctionPointerConversion(Sema &S,
|
||||||
S.Context.getDefaultCallingConvention(
|
S.Context.getDefaultCallingConvention(
|
||||||
/*IsVariadic=*/false, /*IsCXXMethod=*/true));
|
/*IsVariadic=*/false, /*IsCXXMethod=*/true));
|
||||||
// The conversion function is always const.
|
// The conversion function is always const.
|
||||||
ConvExtInfo.TypeQuals = Qualifiers::Const;
|
ConvExtInfo.TypeQuals = Qualifiers();
|
||||||
|
ConvExtInfo.TypeQuals.addConst();
|
||||||
QualType ConvTy =
|
QualType ConvTy =
|
||||||
S.Context.getFunctionType(PtrToFunctionTy, None, ConvExtInfo);
|
S.Context.getFunctionType(PtrToFunctionTy, None, ConvExtInfo);
|
||||||
|
|
||||||
|
@ -1377,7 +1378,8 @@ static void addBlockPointerConversion(Sema &S,
|
||||||
FunctionProtoType::ExtProtoInfo ConversionEPI(
|
FunctionProtoType::ExtProtoInfo ConversionEPI(
|
||||||
S.Context.getDefaultCallingConvention(
|
S.Context.getDefaultCallingConvention(
|
||||||
/*IsVariadic=*/false, /*IsCXXMethod=*/true));
|
/*IsVariadic=*/false, /*IsCXXMethod=*/true));
|
||||||
ConversionEPI.TypeQuals = Qualifiers::Const;
|
ConversionEPI.TypeQuals = Qualifiers();
|
||||||
|
ConversionEPI.TypeQuals.addConst();
|
||||||
QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ConversionEPI);
|
QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ConversionEPI);
|
||||||
|
|
||||||
SourceLocation Loc = IntroducerRange.getBegin();
|
SourceLocation Loc = IntroducerRange.getBegin();
|
||||||
|
|
|
@ -1142,8 +1142,9 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
|
||||||
// function yet (because we haven't yet resolved whether this is a static
|
// 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
|
// or non-static member function). Add it now, on the assumption that this
|
||||||
// is a redeclaration of OldMethod.
|
// is a redeclaration of OldMethod.
|
||||||
unsigned OldQuals = OldMethod->getTypeQualifiers();
|
// FIXME: OpenCL: Need to consider address spaces
|
||||||
unsigned NewQuals = NewMethod->getTypeQualifiers();
|
unsigned OldQuals = OldMethod->getTypeQualifiers().getCVRUQualifiers();
|
||||||
|
unsigned NewQuals = NewMethod->getTypeQualifiers().getCVRUQualifiers();
|
||||||
if (!getLangOpts().CPlusPlus14 && NewMethod->isConstexpr() &&
|
if (!getLangOpts().CPlusPlus14 && NewMethod->isConstexpr() &&
|
||||||
!isa<CXXConstructorDecl>(NewMethod))
|
!isa<CXXConstructorDecl>(NewMethod))
|
||||||
NewQuals |= Qualifiers::Const;
|
NewQuals |= Qualifiers::Const;
|
||||||
|
@ -2823,8 +2824,9 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned FromQuals = FromFunction->getTypeQuals(),
|
// FIXME: OpenCL: Need to consider address spaces
|
||||||
ToQuals = ToFunction->getTypeQuals();
|
unsigned FromQuals = FromFunction->getTypeQuals().getCVRUQualifiers();
|
||||||
|
unsigned ToQuals = ToFunction->getTypeQuals().getCVRUQualifiers();
|
||||||
if (FromQuals != ToQuals) {
|
if (FromQuals != ToQuals) {
|
||||||
PDiag << ft_qualifer_mismatch << ToQuals << FromQuals;
|
PDiag << ft_qualifer_mismatch << ToQuals << FromQuals;
|
||||||
return;
|
return;
|
||||||
|
@ -5065,9 +5067,15 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType,
|
||||||
QualType ClassType = S.Context.getTypeDeclType(ActingContext);
|
QualType ClassType = S.Context.getTypeDeclType(ActingContext);
|
||||||
// [class.dtor]p2: A destructor can be invoked for a const, volatile or
|
// [class.dtor]p2: A destructor can be invoked for a const, volatile or
|
||||||
// const volatile object.
|
// const volatile object.
|
||||||
unsigned Quals = isa<CXXDestructorDecl>(Method) ?
|
Qualifiers Quals;
|
||||||
Qualifiers::Const | Qualifiers::Volatile : Method->getTypeQualifiers();
|
if (isa<CXXDestructorDecl>(Method)) {
|
||||||
QualType ImplicitParamType = S.Context.getCVRQualifiedType(ClassType, Quals);
|
Quals.addConst();
|
||||||
|
Quals.addVolatile();
|
||||||
|
} else {
|
||||||
|
Quals = Method->getTypeQualifiers();
|
||||||
|
}
|
||||||
|
|
||||||
|
QualType ImplicitParamType = S.Context.getQualifiedType(ClassType, Quals);
|
||||||
|
|
||||||
// Set up the conversion sequence as a "bad" conversion, to allow us
|
// Set up the conversion sequence as a "bad" conversion, to allow us
|
||||||
// to exit early.
|
// to exit early.
|
||||||
|
@ -5133,7 +5141,7 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RQ_LValue:
|
case RQ_LValue:
|
||||||
if (!FromClassification.isLValue() && Quals != Qualifiers::Const) {
|
if (!FromClassification.isLValue() && !Quals.hasOnlyConst()) {
|
||||||
// non-const lvalue reference cannot bind to an rvalue
|
// non-const lvalue reference cannot bind to an rvalue
|
||||||
ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, FromType,
|
ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, FromType,
|
||||||
ImplicitParamType);
|
ImplicitParamType);
|
||||||
|
@ -5249,9 +5257,14 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
|
||||||
From = FromRes.get();
|
From = FromRes.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Context.hasSameType(From->getType(), DestType))
|
if (!Context.hasSameType(From->getType(), DestType)) {
|
||||||
|
if (From->getType().getAddressSpace() != DestType.getAddressSpace())
|
||||||
|
From = ImpCastExprToType(From, DestType, CK_AddressSpaceConversion,
|
||||||
|
From->getValueKind()).get();
|
||||||
|
else
|
||||||
From = ImpCastExprToType(From, DestType, CK_NoOp,
|
From = ImpCastExprToType(From, DestType, CK_NoOp,
|
||||||
From->getValueKind()).get();
|
From->getValueKind()).get();
|
||||||
|
}
|
||||||
return From;
|
return From;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12826,7 +12839,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
|
||||||
|
|
||||||
// Check that the object type isn't more qualified than the
|
// Check that the object type isn't more qualified than the
|
||||||
// member function we're calling.
|
// member function we're calling.
|
||||||
Qualifiers funcQuals = Qualifiers::fromCVRMask(proto->getTypeQuals());
|
Qualifiers funcQuals = proto->getTypeQuals();
|
||||||
|
|
||||||
QualType objectType = op->getLHS()->getType();
|
QualType objectType = op->getLHS()->getType();
|
||||||
if (op->getOpcode() == BO_PtrMemI)
|
if (op->getOpcode() == BO_PtrMemI)
|
||||||
|
|
|
@ -8135,7 +8135,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
|
||||||
if (OldMD && OldMD->isConst()) {
|
if (OldMD && OldMD->isConst()) {
|
||||||
const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
|
const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
|
||||||
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
|
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
|
||||||
EPI.TypeQuals |= Qualifiers::Const;
|
EPI.TypeQuals.addConst();
|
||||||
FT = Context.getFunctionType(FPT->getReturnType(),
|
FT = Context.getFunctionType(FPT->getReturnType(),
|
||||||
FPT->getParamTypes(), EPI);
|
FPT->getParamTypes(), EPI);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3078,7 +3078,7 @@ Sema::SubstituteExplicitTemplateArguments(
|
||||||
// "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
|
// "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
|
||||||
// and the end of the function-definition, member-declarator, or
|
// and the end of the function-definition, member-declarator, or
|
||||||
// declarator.
|
// declarator.
|
||||||
unsigned ThisTypeQuals = 0;
|
Qualifiers ThisTypeQuals;
|
||||||
CXXRecordDecl *ThisContext = nullptr;
|
CXXRecordDecl *ThisContext = nullptr;
|
||||||
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
|
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
|
||||||
ThisContext = Method->getParent();
|
ThisContext = Method->getParent();
|
||||||
|
@ -4657,8 +4657,7 @@ AddImplicitObjectParameterType(ASTContext &Context,
|
||||||
// The standard doesn't say explicitly, but we pick the appropriate kind of
|
// The standard doesn't say explicitly, but we pick the appropriate kind of
|
||||||
// reference type based on [over.match.funcs]p4.
|
// reference type based on [over.match.funcs]p4.
|
||||||
QualType ArgTy = Context.getTypeDeclType(Method->getParent());
|
QualType ArgTy = Context.getTypeDeclType(Method->getParent());
|
||||||
ArgTy = Context.getQualifiedType(ArgTy,
|
ArgTy = Context.getQualifiedType(ArgTy, Method->getTypeQualifiers());
|
||||||
Qualifiers::fromCVRMask(Method->getTypeQualifiers()));
|
|
||||||
if (Method->getRefQualifier() == RQ_RValue)
|
if (Method->getRefQualifier() == RQ_RValue)
|
||||||
ArgTy = Context.getRValueReferenceType(ArgTy);
|
ArgTy = Context.getRValueReferenceType(ArgTy);
|
||||||
else
|
else
|
||||||
|
|
|
@ -907,7 +907,7 @@ namespace {
|
||||||
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
|
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
|
||||||
FunctionProtoTypeLoc TL,
|
FunctionProtoTypeLoc TL,
|
||||||
CXXRecordDecl *ThisContext,
|
CXXRecordDecl *ThisContext,
|
||||||
unsigned ThisTypeQuals,
|
Qualifiers ThisTypeQuals,
|
||||||
Fn TransformExceptionSpec);
|
Fn TransformExceptionSpec);
|
||||||
|
|
||||||
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
|
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
|
||||||
|
@ -1427,7 +1427,7 @@ template<typename Fn>
|
||||||
QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
|
QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
|
||||||
FunctionProtoTypeLoc TL,
|
FunctionProtoTypeLoc TL,
|
||||||
CXXRecordDecl *ThisContext,
|
CXXRecordDecl *ThisContext,
|
||||||
unsigned ThisTypeQuals,
|
Qualifiers ThisTypeQuals,
|
||||||
Fn TransformExceptionSpec) {
|
Fn TransformExceptionSpec) {
|
||||||
// We need a local instantiation scope for this function prototype.
|
// We need a local instantiation scope for this function prototype.
|
||||||
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
|
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
|
||||||
|
@ -1666,7 +1666,7 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
|
||||||
SourceLocation Loc,
|
SourceLocation Loc,
|
||||||
DeclarationName Entity,
|
DeclarationName Entity,
|
||||||
CXXRecordDecl *ThisContext,
|
CXXRecordDecl *ThisContext,
|
||||||
unsigned ThisTypeQuals) {
|
Qualifiers ThisTypeQuals) {
|
||||||
assert(!CodeSynthesisContexts.empty() &&
|
assert(!CodeSynthesisContexts.empty() &&
|
||||||
"Cannot perform an instantiation without some context on the "
|
"Cannot perform an instantiation without some context on the "
|
||||||
"instantiation stack");
|
"instantiation stack");
|
||||||
|
@ -2148,7 +2148,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
||||||
NamedDecl *ND = dyn_cast<NamedDecl>(I->NewDecl);
|
NamedDecl *ND = dyn_cast<NamedDecl>(I->NewDecl);
|
||||||
CXXRecordDecl *ThisContext =
|
CXXRecordDecl *ThisContext =
|
||||||
dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
|
dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
|
||||||
CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0,
|
CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(),
|
||||||
ND && ND->isCXXInstanceMember());
|
ND && ND->isCXXInstanceMember());
|
||||||
|
|
||||||
Attr *NewAttr =
|
Attr *NewAttr =
|
||||||
|
@ -2343,7 +2343,7 @@ bool Sema::InstantiateInClassInitializer(
|
||||||
|
|
||||||
// Instantiate the initializer.
|
// Instantiate the initializer.
|
||||||
ActOnStartCXXInClassMemberInitializer();
|
ActOnStartCXXInClassMemberInitializer();
|
||||||
CXXThisScopeRAII ThisScope(*this, Instantiation->getParent(), /*TypeQuals=*/0);
|
CXXThisScopeRAII ThisScope(*this, Instantiation->getParent(), Qualifiers());
|
||||||
|
|
||||||
ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
|
ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
|
||||||
/*CXXDirectInit=*/false);
|
/*CXXDirectInit=*/false);
|
||||||
|
|
|
@ -295,7 +295,7 @@ static void instantiateOMPDeclareSimdDeclAttr(
|
||||||
PVD, FD->getParamDecl(PVD->getFunctionScopeIndex()));
|
PVD, FD->getParamDecl(PVD->getFunctionScopeIndex()));
|
||||||
return S.SubstExpr(E, TemplateArgs);
|
return S.SubstExpr(E, TemplateArgs);
|
||||||
}
|
}
|
||||||
Sema::CXXThisScopeRAII ThisScope(S, ThisContext, /*TypeQuals=*/0,
|
Sema::CXXThisScopeRAII ThisScope(S, ThisContext, Qualifiers(),
|
||||||
FD->isCXXInstanceMember());
|
FD->isCXXInstanceMember());
|
||||||
return S.SubstExpr(E, TemplateArgs);
|
return S.SubstExpr(E, TemplateArgs);
|
||||||
};
|
};
|
||||||
|
@ -355,7 +355,7 @@ void Sema::InstantiateAttrsForDecl(
|
||||||
// applicable to template declaration, we'll need to add them here.
|
// applicable to template declaration, we'll need to add them here.
|
||||||
CXXThisScopeRAII ThisScope(
|
CXXThisScopeRAII ThisScope(
|
||||||
*this, dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()),
|
*this, dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()),
|
||||||
/*TypeQuals*/ 0, ND->isCXXInstanceMember());
|
Qualifiers(), ND->isCXXInstanceMember());
|
||||||
|
|
||||||
Attr *NewAttr = sema::instantiateTemplateAttributeForDecl(
|
Attr *NewAttr = sema::instantiateTemplateAttributeForDecl(
|
||||||
TmplAttr, Context, *this, TemplateArgs);
|
TmplAttr, Context, *this, TemplateArgs);
|
||||||
|
@ -474,7 +474,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||||
NamedDecl *ND = dyn_cast<NamedDecl>(New);
|
NamedDecl *ND = dyn_cast<NamedDecl>(New);
|
||||||
CXXRecordDecl *ThisContext =
|
CXXRecordDecl *ThisContext =
|
||||||
dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
|
dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
|
||||||
CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0,
|
CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(),
|
||||||
ND && ND->isCXXInstanceMember());
|
ND && ND->isCXXInstanceMember());
|
||||||
|
|
||||||
Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,
|
Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,
|
||||||
|
@ -2822,7 +2822,7 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
|
||||||
cast<DeclRefExpr>(D->getCombinerOut())->getDecl(),
|
cast<DeclRefExpr>(D->getCombinerOut())->getDecl(),
|
||||||
cast<DeclRefExpr>(NewDRD->getCombinerOut())->getDecl());
|
cast<DeclRefExpr>(NewDRD->getCombinerOut())->getDecl());
|
||||||
auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner);
|
auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner);
|
||||||
Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, /*TypeQuals*/ 0,
|
Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(),
|
||||||
ThisContext);
|
ThisContext);
|
||||||
SubstCombiner = SemaRef.SubstExpr(D->getCombiner(), TemplateArgs).get();
|
SubstCombiner = SemaRef.SubstExpr(D->getCombiner(), TemplateArgs).get();
|
||||||
SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner);
|
SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner);
|
||||||
|
@ -3441,7 +3441,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
|
||||||
assert(Params.empty() && "parameter vector is non-empty at start");
|
assert(Params.empty() && "parameter vector is non-empty at start");
|
||||||
|
|
||||||
CXXRecordDecl *ThisContext = nullptr;
|
CXXRecordDecl *ThisContext = nullptr;
|
||||||
unsigned ThisTypeQuals = 0;
|
Qualifiers ThisTypeQuals;
|
||||||
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
|
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
|
||||||
ThisContext = cast<CXXRecordDecl>(Owner);
|
ThisContext = cast<CXXRecordDecl>(Owner);
|
||||||
ThisTypeQuals = Method->getTypeQualifiers();
|
ThisTypeQuals = Method->getTypeQualifiers();
|
||||||
|
|
|
@ -1873,8 +1873,7 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy){
|
static std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy){
|
||||||
std::string Quals =
|
std::string Quals = FnTy->getTypeQuals().getAsString();
|
||||||
Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString();
|
|
||||||
|
|
||||||
switch (FnTy->getRefQualifier()) {
|
switch (FnTy->getRefQualifier()) {
|
||||||
case RQ_None:
|
case RQ_None:
|
||||||
|
@ -1916,7 +1915,7 @@ static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc,
|
||||||
QualifiedFunctionKind QFK) {
|
QualifiedFunctionKind QFK) {
|
||||||
// Does T refer to a function type with a cv-qualifier or a ref-qualifier?
|
// Does T refer to a function type with a cv-qualifier or a ref-qualifier?
|
||||||
const FunctionProtoType *FPT = T->getAs<FunctionProtoType>();
|
const FunctionProtoType *FPT = T->getAs<FunctionProtoType>();
|
||||||
if (!FPT || (FPT->getTypeQuals() == 0 && FPT->getRefQualifier() == RQ_None))
|
if (!FPT || (FPT->getTypeQuals().empty() && FPT->getRefQualifier() == RQ_None))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
S.Diag(Loc, diag::err_compound_qualified_function_type)
|
S.Diag(Loc, diag::err_compound_qualified_function_type)
|
||||||
|
@ -3950,7 +3949,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||||
|
|
||||||
// Does T refer to a function type with a cv-qualifier or a ref-qualifier?
|
// Does T refer to a function type with a cv-qualifier or a ref-qualifier?
|
||||||
bool IsQualifiedFunction = T->isFunctionProtoType() &&
|
bool IsQualifiedFunction = T->isFunctionProtoType() &&
|
||||||
(T->castAs<FunctionProtoType>()->getTypeQuals() != 0 ||
|
(!T->castAs<FunctionProtoType>()->getTypeQuals().empty() ||
|
||||||
T->castAs<FunctionProtoType>()->getRefQualifier() != RQ_None);
|
T->castAs<FunctionProtoType>()->getRefQualifier() != RQ_None);
|
||||||
|
|
||||||
// If T is 'decltype(auto)', the only declarators we can have are parens
|
// If T is 'decltype(auto)', the only declarators we can have are parens
|
||||||
|
@ -4699,7 +4698,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||||
EPI.ExtInfo = EI;
|
EPI.ExtInfo = EI;
|
||||||
EPI.Variadic = FTI.isVariadic;
|
EPI.Variadic = FTI.isVariadic;
|
||||||
EPI.HasTrailingReturn = FTI.hasTrailingReturnType();
|
EPI.HasTrailingReturn = FTI.hasTrailingReturnType();
|
||||||
EPI.TypeQuals = FTI.TypeQuals;
|
EPI.TypeQuals.addCVRUQualifiers(FTI.TypeQuals);
|
||||||
EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
|
EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
|
||||||
: FTI.RefQualifierIsLValueRef? RQ_LValue
|
: FTI.RefQualifierIsLValueRef? RQ_LValue
|
||||||
: RQ_RValue;
|
: RQ_RValue;
|
||||||
|
@ -4826,7 +4825,24 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||||
Exceptions,
|
Exceptions,
|
||||||
EPI.ExceptionSpec);
|
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 = Context.getFunctionType(T, ParamTys, EPI);
|
||||||
|
T = state.getSema().Context.getAddrSpaceQualType(T, AS);
|
||||||
|
} else {
|
||||||
|
T = Context.getFunctionType(T, ParamTys, EPI);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -5031,7 +5047,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||||
|
|
||||||
// Strip the cv-qualifiers and ref-qualifiers from the type.
|
// Strip the cv-qualifiers and ref-qualifiers from the type.
|
||||||
FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
|
FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
|
||||||
EPI.TypeQuals = 0;
|
EPI.TypeQuals.removeCVRQualifiers();
|
||||||
EPI.RefQualifier = RQ_None;
|
EPI.RefQualifier = RQ_None;
|
||||||
|
|
||||||
T = Context.getFunctionType(FnTy->getReturnType(), FnTy->getParamTypes(),
|
T = Context.getFunctionType(FnTy->getReturnType(), FnTy->getParamTypes(),
|
||||||
|
|
|
@ -597,7 +597,7 @@ public:
|
||||||
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
|
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
|
||||||
FunctionProtoTypeLoc TL,
|
FunctionProtoTypeLoc TL,
|
||||||
CXXRecordDecl *ThisContext,
|
CXXRecordDecl *ThisContext,
|
||||||
unsigned ThisTypeQuals,
|
Qualifiers ThisTypeQuals,
|
||||||
Fn TransformExceptionSpec);
|
Fn TransformExceptionSpec);
|
||||||
|
|
||||||
bool TransformExceptionSpec(SourceLocation Loc,
|
bool TransformExceptionSpec(SourceLocation Loc,
|
||||||
|
@ -4274,8 +4274,11 @@ QualType TreeTransform<Derived>::RebuildQualifiedType(QualType T,
|
||||||
// C++ [dcl.fct]p7:
|
// C++ [dcl.fct]p7:
|
||||||
// [When] adding cv-qualifications on top of the function type [...] the
|
// [When] adding cv-qualifications on top of the function type [...] the
|
||||||
// cv-qualifiers are ignored.
|
// cv-qualifiers are ignored.
|
||||||
if (T->isFunctionType())
|
if (T->isFunctionType()) {
|
||||||
|
T = SemaRef.getASTContext().getAddrSpaceQualType(T,
|
||||||
|
Quals.getAddressSpace());
|
||||||
return T;
|
return T;
|
||||||
|
}
|
||||||
|
|
||||||
// C++ [dcl.ref]p1:
|
// C++ [dcl.ref]p1:
|
||||||
// when the cv-qualifiers are introduced through the use of a typedef-name
|
// when the cv-qualifiers are introduced through the use of a typedef-name
|
||||||
|
@ -5242,7 +5245,7 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
|
||||||
SmallVector<QualType, 4> ExceptionStorage;
|
SmallVector<QualType, 4> ExceptionStorage;
|
||||||
TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
|
TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
|
||||||
return getDerived().TransformFunctionProtoType(
|
return getDerived().TransformFunctionProtoType(
|
||||||
TLB, TL, nullptr, 0,
|
TLB, TL, nullptr, Qualifiers(),
|
||||||
[&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
|
[&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
|
||||||
return This->TransformExceptionSpec(TL.getBeginLoc(), ESI,
|
return This->TransformExceptionSpec(TL.getBeginLoc(), ESI,
|
||||||
ExceptionStorage, Changed);
|
ExceptionStorage, Changed);
|
||||||
|
@ -5252,7 +5255,7 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
|
||||||
template<typename Derived> template<typename Fn>
|
template<typename Derived> template<typename Fn>
|
||||||
QualType TreeTransform<Derived>::TransformFunctionProtoType(
|
QualType TreeTransform<Derived>::TransformFunctionProtoType(
|
||||||
TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext,
|
TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext,
|
||||||
unsigned ThisTypeQuals, Fn TransformExceptionSpec) {
|
Qualifiers ThisTypeQuals, Fn TransformExceptionSpec) {
|
||||||
|
|
||||||
// Transform the parameters and return type.
|
// Transform the parameters and return type.
|
||||||
//
|
//
|
||||||
|
@ -11024,7 +11027,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
|
||||||
SmallVector<QualType, 4> ExceptionStorage;
|
SmallVector<QualType, 4> ExceptionStorage;
|
||||||
TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
|
TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
|
||||||
QualType NewCallOpType = TransformFunctionProtoType(
|
QualType NewCallOpType = TransformFunctionProtoType(
|
||||||
NewCallOpTLBuilder, OldCallOpFPTL, nullptr, 0,
|
NewCallOpTLBuilder, OldCallOpFPTL, nullptr, Qualifiers(),
|
||||||
[&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
|
[&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
|
||||||
return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,
|
return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,
|
||||||
ExceptionStorage, Changed);
|
ExceptionStorage, Changed);
|
||||||
|
|
|
@ -6050,7 +6050,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
|
||||||
|
|
||||||
EPI.Variadic = Record[Idx++];
|
EPI.Variadic = Record[Idx++];
|
||||||
EPI.HasTrailingReturn = Record[Idx++];
|
EPI.HasTrailingReturn = Record[Idx++];
|
||||||
EPI.TypeQuals = Record[Idx++];
|
EPI.TypeQuals = Qualifiers::fromOpaqueValue(Record[Idx++]);
|
||||||
EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]);
|
EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]);
|
||||||
SmallVector<QualType, 8> ExceptionStorage;
|
SmallVector<QualType, 8> ExceptionStorage;
|
||||||
readExceptionSpec(*Loc.F, ExceptionStorage, EPI.ExceptionSpec, Record, Idx);
|
readExceptionSpec(*Loc.F, ExceptionStorage, EPI.ExceptionSpec, Record, Idx);
|
||||||
|
|
|
@ -310,7 +310,7 @@ void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
|
||||||
|
|
||||||
Record.push_back(T->isVariadic());
|
Record.push_back(T->isVariadic());
|
||||||
Record.push_back(T->hasTrailingReturn());
|
Record.push_back(T->hasTrailingReturn());
|
||||||
Record.push_back(T->getTypeQuals());
|
Record.push_back(T->getTypeQuals().getAsOpaqueValue());
|
||||||
Record.push_back(static_cast<unsigned>(T->getRefQualifier()));
|
Record.push_back(static_cast<unsigned>(T->getRefQualifier()));
|
||||||
addExceptionSpec(T, Record);
|
addExceptionSpec(T, Record);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
// 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)
|
|
@ -9,13 +9,16 @@ struct S{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T S<T>::foo() { return a;}
|
T S<T>::foo() { return a;}
|
||||||
|
|
||||||
//CHECK: %struct.S = type { i32 }
|
// CHECK: %struct.S = type { i32 }
|
||||||
//CHECK: %struct.S.0 = type { i32 addrspace(4)* }
|
// CHECK: %struct.S.0 = type { i32 addrspace(4)* }
|
||||||
//CHECK: %struct.S.1 = type { i32 addrspace(1)* }
|
// CHECK: %struct.S.1 = type { i32 addrspace(1)* }
|
||||||
|
|
||||||
//CHECK: i32 @_ZN1SIiE3fooEv(%struct.S* %this)
|
// CHECK: %0 = addrspacecast %struct.S* %sint to %struct.S addrspace(4)*
|
||||||
//CHECK: i32 addrspace(4)* @_ZN1SIPU3AS4iE3fooEv(%struct.S.0* %this)
|
// CHECK: %call = call i32 @_ZNU3AS41SIiE3fooEv(%struct.S addrspace(4)* %0) #1
|
||||||
//CHECK: i32 addrspace(1)* @_ZN1SIPU3AS1iE3fooEv(%struct.S.1* %this)
|
// 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
|
||||||
|
|
||||||
void bar(){
|
void bar(){
|
||||||
S<int> sint;
|
S<int> sint;
|
||||||
|
|
|
@ -4,7 +4,9 @@ template <typename T>
|
||||||
struct S {
|
struct S {
|
||||||
T a; // expected-error{{field may not be qualified with an address space}}
|
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}}
|
T f1(); // expected-error{{function type may not be qualified with an address space}}
|
||||||
void f2(T); // expected-error{{parameter 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}}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -8370,7 +8370,7 @@ unsigned clang_CXXMethod_isConst(CXCursor C) {
|
||||||
const Decl *D = cxcursor::getCursorDecl(C);
|
const Decl *D = cxcursor::getCursorDecl(C);
|
||||||
const CXXMethodDecl *Method =
|
const CXXMethodDecl *Method =
|
||||||
D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
|
D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
|
||||||
return (Method && (Method->getTypeQualifiers() & Qualifiers::Const)) ? 1 : 0;
|
return (Method && Method->getTypeQualifiers().hasConst()) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned clang_CXXMethod_isDefaulted(CXCursor C) {
|
unsigned clang_CXXMethod_isDefaulted(CXCursor C) {
|
||||||
|
|
Loading…
Reference in New Issue