aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp504
1 files changed, 408 insertions, 96 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index f6ad132cde83..f3747eaa5cb5 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -22,7 +21,6 @@
#include "clang/AST/Expr.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeLocVisitor.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
@@ -30,9 +28,11 @@
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
@@ -100,20 +100,27 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
case AttributeList::AT_ObjCGC: \
case AttributeList::AT_ObjCOwnership
-// Function type attributes.
-#define FUNCTION_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_NoReturn: \
+// Calling convention attributes.
+#define CALLING_CONV_ATTRS_CASELIST \
case AttributeList::AT_CDecl: \
case AttributeList::AT_FastCall: \
case AttributeList::AT_StdCall: \
case AttributeList::AT_ThisCall: \
case AttributeList::AT_Pascal: \
+ case AttributeList::AT_SwiftCall: \
case AttributeList::AT_VectorCall: \
case AttributeList::AT_MSABI: \
case AttributeList::AT_SysVABI: \
- case AttributeList::AT_Regparm: \
case AttributeList::AT_Pcs: \
- case AttributeList::AT_IntelOclBicc
+ case AttributeList::AT_IntelOclBicc: \
+ case AttributeList::AT_PreserveMost: \
+ case AttributeList::AT_PreserveAll
+
+// Function type attributes.
+#define FUNCTION_TYPE_ATTRS_CASELIST \
+ case AttributeList::AT_NoReturn: \
+ case AttributeList::AT_Regparm: \
+ CALLING_CONV_ATTRS_CASELIST
// Microsoft-specific type qualifiers.
#define MS_TYPE_ATTRS_CASELIST \
@@ -239,7 +246,7 @@ namespace {
savedAttrs.back()->setNext(nullptr);
}
};
-}
+} // end anonymous namespace
static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) {
attr.setNext(head);
@@ -727,6 +734,7 @@ static void diagnoseAndRemoveTypeQualifiers(Sema &S, const DeclSpec &DS,
// it; they probably didn't mean to specify a redundant qualifier.
typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc;
for (QualLoc Qual : {QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()),
+ QualLoc(DeclSpec::TQ_restrict, DS.getRestrictSpecLoc()),
QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()),
QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())}) {
if (!(RemoveTQs & Qual.first))
@@ -743,6 +751,47 @@ static void diagnoseAndRemoveTypeQualifiers(Sema &S, const DeclSpec &DS,
}
}
+/// Return true if this is omitted block return type. Also check type
+/// attributes and type qualifiers when returning true.
+static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator,
+ QualType Result) {
+ if (!isOmittedBlockReturnType(declarator))
+ return false;
+
+ // Warn if we see type attributes for omitted return type on a block literal.
+ AttributeList *&attrs =
+ declarator.getMutableDeclSpec().getAttributes().getListRef();
+ AttributeList *prev = nullptr;
+ for (AttributeList *cur = attrs; cur; cur = cur->getNext()) {
+ AttributeList &attr = *cur;
+ // Skip attributes that were marked to be invalid or non-type
+ // attributes.
+ if (attr.isInvalid() || !attr.isTypeAttr()) {
+ prev = cur;
+ continue;
+ }
+ S.Diag(attr.getLoc(),
+ diag::warn_block_literal_attributes_on_omitted_return_type)
+ << attr.getName();
+ // Remove cur from the list.
+ if (prev) {
+ prev->setNext(cur->getNext());
+ prev = cur;
+ } else {
+ attrs = cur->getNext();
+ }
+ }
+
+ // Warn if we see type qualifiers for omitted return type on a block literal.
+ const DeclSpec &DS = declarator.getDeclSpec();
+ unsigned TypeQuals = DS.getTypeQualifiers();
+ diagnoseAndRemoveTypeQualifiers(S, DS, TypeQuals, Result, (unsigned)-1,
+ diag::warn_block_literal_qualifiers_on_omitted_return_type);
+ declarator.getMutableDeclSpec().ClearTypeQualifiers();
+
+ return true;
+}
+
/// Apply Objective-C type arguments to the given type.
static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
ArrayRef<TypeSourceInfo *> typeArgs,
@@ -1171,6 +1220,21 @@ TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers(
return CreateParsedType(Result, ResultTInfo);
}
+static StringRef getImageAccessAttrStr(AttributeList *attrs) {
+ if (attrs) {
+
+ AttributeList *Next;
+ do {
+ AttributeList &Attr = *attrs;
+ Next = Attr.getNext();
+ if (Attr.getKind() == AttributeList::AT_OpenCLAccess) {
+ return Attr.getName()->getName();
+ }
+ } while (Next);
+ }
+ return "";
+}
+
/// \brief Convert the specified declspec to the appropriate type
/// object.
/// \param state Specifies the declarator containing the declaration specifier
@@ -1244,7 +1308,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = Context.getAutoDeductType();
break;
} else if (declarator.getContext() == Declarator::LambdaExprContext ||
- isOmittedBlockReturnType(declarator)) {
+ checkOmittedBlockReturnType(S, declarator,
+ Context.DependentTy)) {
Result = Context.DependentTy;
break;
}
@@ -1332,7 +1397,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
case DeclSpec::TST_int128:
if (!S.Context.getTargetInfo().hasInt128Type())
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_int128_unsupported);
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
+ << "__int128";
if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
Result = Context.UnsignedInt128Ty;
else
@@ -1354,7 +1420,14 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
declarator.setInvalidType(true);
}
break;
+ case DeclSpec::TST_float128:
+ if (!S.Context.getTargetInfo().hasFloat128Type())
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
+ << "__float128";
+ Result = Context.Float128Ty;
+ break;
case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool
+ break;
case DeclSpec::TST_decimal32: // _Decimal32
case DeclSpec::TST_decimal64: // _Decimal64
case DeclSpec::TST_decimal128: // _Decimal128
@@ -1423,9 +1496,18 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
declarator.setInvalidType(true);
}
} else if (!S.getOpenCLOptions().cl_khr_gl_msaa_sharing &&
- (Result->isImage2dMSAAT() || Result->isImage2dArrayMSAAT() ||
- Result->isImage2dArrayMSAATDepth() ||
- Result->isImage2dMSAATDepth())) {
+ (Result->isOCLImage2dArrayMSAADepthROType() ||
+ Result->isOCLImage2dArrayMSAADepthWOType() ||
+ Result->isOCLImage2dArrayMSAADepthRWType() ||
+ Result->isOCLImage2dArrayMSAAROType() ||
+ Result->isOCLImage2dArrayMSAARWType() ||
+ Result->isOCLImage2dArrayMSAAWOType() ||
+ Result->isOCLImage2dMSAADepthROType() ||
+ Result->isOCLImage2dMSAADepthRWType() ||
+ Result->isOCLImage2dMSAADepthWOType() ||
+ Result->isOCLImage2dMSAAROType() ||
+ Result->isOCLImage2dMSAARWType() ||
+ Result->isOCLImage2dMSAAWOType())) {
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
<< Result << "cl_khr_gl_msaa_sharing";
declarator.setInvalidType(true);
@@ -1539,6 +1621,16 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
break;
+#define GENERIC_IMAGE_TYPE(ImgType, Id) \
+ case DeclSpec::TST_##ImgType##_t: \
+ Result = llvm::StringSwitch<QualType>( \
+ getImageAccessAttrStr(DS.getAttributes().getList())) \
+ .Cases("write_only", "__write_only", Context.Id##WOTy) \
+ .Cases("read_write", "__read_write", Context.Id##RWTy) \
+ .Default(Context.Id##ROTy); \
+ break;
+#include "clang/Basic/OpenCLImageTypes.def"
+
case DeclSpec::TST_error:
Result = Context.IntTy;
declarator.setInvalidType(true);
@@ -1693,12 +1785,13 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
}
QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
- unsigned CVRA, const DeclSpec *DS) {
+ unsigned CVRAU, const DeclSpec *DS) {
if (T.isNull())
return QualType();
- // Convert from DeclSpec::TQ to Qualifiers::TQ by just dropping TQ_atomic.
- unsigned CVR = CVRA & ~DeclSpec::TQ_atomic;
+ // Convert from DeclSpec::TQ to Qualifiers::TQ by just dropping TQ_atomic and
+ // TQ_unaligned;
+ unsigned CVR = CVRAU & ~(DeclSpec::TQ_atomic | DeclSpec::TQ_unaligned);
// C11 6.7.3/5:
// If the same qualifier appears more than once in the same
@@ -1708,7 +1801,7 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
// It's not specified what happens when the _Atomic qualifier is applied to
// a type specified with the _Atomic specifier, but we assume that this
// should be treated as if the _Atomic qualifier appeared multiple times.
- if (CVRA & DeclSpec::TQ_atomic && !T->isAtomicType()) {
+ if (CVRAU & DeclSpec::TQ_atomic && !T->isAtomicType()) {
// C11 6.7.3/5:
// If other qualifiers appear along with the _Atomic qualifier in a
// specifier-qualifier-list, the resulting type is the so-qualified
@@ -1725,7 +1818,9 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
return BuildQualifiedType(T, Loc, Split.Quals);
}
- return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR), DS);
+ Qualifiers Q = Qualifiers::fromCVRMask(CVR);
+ Q.setUnaligned(CVRAU & DeclSpec::TQ_unaligned);
+ return BuildQualifiedType(T, Loc, Q, DS);
}
/// \brief Build a paren type including \p T.
@@ -1821,7 +1916,7 @@ namespace {
///
/// The values of this enum are used in diagnostics.
enum QualifiedFunctionKind { QFK_BlockPointer, QFK_Pointer, QFK_Reference };
-}
+} // end anonymous namespace
/// Check whether the type T is a qualified function type, and if it is,
/// diagnose that it cannot be contained within the given kind of declarator.
@@ -1968,10 +2063,10 @@ static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
} Diagnoser;
return S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser,
- S.LangOpts.GNUMode).isInvalid();
+ S.LangOpts.GNUMode ||
+ S.LangOpts.OpenCL).isInvalid();
}
-
/// \brief Build an array type.
///
/// \param T The type of each element in the array.
@@ -2150,15 +2245,8 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
// If this is not C99, extwarn about VLA's and C99 array size modifiers.
if (!getLangOpts().C99) {
if (T->isVariableArrayType()) {
- // Prohibit the use of non-POD types in VLAs.
- QualType BaseT = Context.getBaseElementType(T);
- if (!T->isDependentType() && isCompleteType(Loc, BaseT) &&
- !BaseT.isPODType(Context) && !BaseT->isObjCLifetimeType()) {
- Diag(Loc, diag::err_vla_non_pod) << BaseT;
- return QualType();
- }
// Prohibit the use of VLAs during template argument deduction.
- else if (isSFINAEContext()) {
+ if (isSFINAEContext()) {
Diag(Loc, diag::err_vla_in_sfinae);
return QualType();
}
@@ -2176,6 +2264,18 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Diag(Loc, diag::warn_vla_used);
}
+ // OpenCL v2.0 s6.12.5 - Arrays of blocks are not supported.
+ // OpenCL v2.0 s6.16.13.1 - Arrays of pipe type are not supported.
+ // OpenCL v2.0 s6.9.b - Arrays of image/sampler type are not supported.
+ if (getLangOpts().OpenCL) {
+ const QualType ArrType = Context.getBaseElementType(T);
+ if (ArrType->isBlockPointerType() || ArrType->isPipeType() ||
+ ArrType->isSamplerT() || ArrType->isImageType()) {
+ Diag(Loc, diag::err_opencl_invalid_type_array) << ArrType;
+ return QualType();
+ }
+ }
+
return T;
}
@@ -2184,10 +2284,16 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
/// Run the required checks for the extended vector type.
QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
SourceLocation AttrLoc) {
- // unlike gcc's vector_size attribute, we do not allow vectors to be defined
+ // Unlike gcc's vector_size attribute, we do not allow vectors to be defined
// in conjunction with complex types (pointers, arrays, functions, etc.).
- if (!T->isDependentType() &&
- !T->isIntegerType() && !T->isRealFloatingType()) {
+ //
+ // Additionally, OpenCL prohibits vectors of booleans (they're considered a
+ // reserved data type under OpenCL v2.0 s6.1.4), we don't support selects
+ // on bitvectors, and we have no well-defined ABI for bitvectors, so vectors
+ // of bool aren't allowed.
+ if ((!T->isDependentType() && !T->isIntegerType() &&
+ !T->isRealFloatingType()) ||
+ T->isBooleanType()) {
Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T;
return QualType();
}
@@ -2201,7 +2307,7 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
return QualType();
}
- // unlike gcc's vector_size attribute, the size is specified as the
+ // Unlike gcc's vector_size attribute, the size is specified as the
// number of elements, not the number of bytes.
unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
@@ -2247,6 +2353,74 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) {
return false;
}
+/// Check the extended parameter information. Most of the necessary
+/// checking should occur when applying the parameter attribute; the
+/// only other checks required are positional restrictions.
+static void checkExtParameterInfos(Sema &S, ArrayRef<QualType> paramTypes,
+ const FunctionProtoType::ExtProtoInfo &EPI,
+ llvm::function_ref<SourceLocation(unsigned)> getParamLoc) {
+ assert(EPI.ExtParameterInfos && "shouldn't get here without param infos");
+
+ bool hasCheckedSwiftCall = false;
+ auto checkForSwiftCC = [&](unsigned paramIndex) {
+ // Only do this once.
+ if (hasCheckedSwiftCall) return;
+ hasCheckedSwiftCall = true;
+ if (EPI.ExtInfo.getCC() == CC_Swift) return;
+ S.Diag(getParamLoc(paramIndex), diag::err_swift_param_attr_not_swiftcall)
+ << getParameterABISpelling(EPI.ExtParameterInfos[paramIndex].getABI());
+ };
+
+ for (size_t paramIndex = 0, numParams = paramTypes.size();
+ paramIndex != numParams; ++paramIndex) {
+ switch (EPI.ExtParameterInfos[paramIndex].getABI()) {
+ // Nothing interesting to check for orindary-ABI parameters.
+ case ParameterABI::Ordinary:
+ continue;
+
+ // swift_indirect_result parameters must be a prefix of the function
+ // arguments.
+ case ParameterABI::SwiftIndirectResult:
+ checkForSwiftCC(paramIndex);
+ if (paramIndex != 0 &&
+ EPI.ExtParameterInfos[paramIndex - 1].getABI()
+ != ParameterABI::SwiftIndirectResult) {
+ S.Diag(getParamLoc(paramIndex),
+ diag::err_swift_indirect_result_not_first);
+ }
+ continue;
+
+ // swift_context parameters must be the last parameter except for
+ // a possible swift_error parameter.
+ case ParameterABI::SwiftContext:
+ checkForSwiftCC(paramIndex);
+ if (!(paramIndex == numParams - 1 ||
+ (paramIndex == numParams - 2 &&
+ EPI.ExtParameterInfos[numParams - 1].getABI()
+ == ParameterABI::SwiftErrorResult))) {
+ S.Diag(getParamLoc(paramIndex),
+ diag::err_swift_context_not_before_swift_error_result);
+ }
+ continue;
+
+ // swift_error parameters must be the last parameter.
+ case ParameterABI::SwiftErrorResult:
+ checkForSwiftCC(paramIndex);
+ if (paramIndex != numParams - 1) {
+ S.Diag(getParamLoc(paramIndex),
+ diag::err_swift_error_result_not_last);
+ } else if (paramIndex == 0 ||
+ EPI.ExtParameterInfos[paramIndex - 1].getABI()
+ != ParameterABI::SwiftContext) {
+ S.Diag(getParamLoc(paramIndex),
+ diag::err_swift_error_result_not_after_swift_context);
+ }
+ continue;
+ }
+ llvm_unreachable("bad ABI kind");
+ }
+}
+
QualType Sema::BuildFunctionType(QualType T,
MutableArrayRef<QualType> ParamTypes,
SourceLocation Loc, DeclarationName Entity,
@@ -2271,6 +2445,11 @@ QualType Sema::BuildFunctionType(QualType T,
ParamTypes[Idx] = ParamType;
}
+ if (EPI.ExtParameterInfos) {
+ checkExtParameterInfos(*this, ParamTypes, EPI,
+ [=](unsigned i) { return Loc; });
+ }
+
if (Invalid)
return QualType();
@@ -2477,7 +2656,8 @@ void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
SourceLocation ConstQualLoc,
SourceLocation VolatileQualLoc,
SourceLocation RestrictQualLoc,
- SourceLocation AtomicQualLoc) {
+ SourceLocation AtomicQualLoc,
+ SourceLocation UnalignedQualLoc) {
if (!Quals)
return;
@@ -2485,26 +2665,27 @@ void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
const char *Name;
unsigned Mask;
SourceLocation Loc;
- } const QualKinds[4] = {
+ } const QualKinds[5] = {
{ "const", DeclSpec::TQ_const, ConstQualLoc },
{ "volatile", DeclSpec::TQ_volatile, VolatileQualLoc },
{ "restrict", DeclSpec::TQ_restrict, RestrictQualLoc },
+ { "__unaligned", DeclSpec::TQ_unaligned, UnalignedQualLoc },
{ "_Atomic", DeclSpec::TQ_atomic, AtomicQualLoc }
};
SmallString<32> QualStr;
unsigned NumQuals = 0;
SourceLocation Loc;
- FixItHint FixIts[4];
+ FixItHint FixIts[5];
// Build a string naming the redundant qualifiers.
- for (unsigned I = 0; I != 4; ++I) {
- if (Quals & QualKinds[I].Mask) {
+ for (auto &E : QualKinds) {
+ if (Quals & E.Mask) {
if (!QualStr.empty()) QualStr += ' ';
- QualStr += QualKinds[I].Name;
+ QualStr += E.Name;
// If we have a location for the qualifier, offer a fixit.
- SourceLocation QualLoc = QualKinds[I].Loc;
+ SourceLocation QualLoc = E.Loc;
if (QualLoc.isValid()) {
FixIts[NumQuals] = FixItHint::CreateRemoval(QualLoc);
if (Loc.isInvalid() ||
@@ -2550,7 +2731,8 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
SourceLocation::getFromRawEncoding(PTI.ConstQualLoc),
SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc),
SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc),
- SourceLocation::getFromRawEncoding(PTI.AtomicQualLoc));
+ SourceLocation::getFromRawEncoding(PTI.AtomicQualLoc),
+ SourceLocation::getFromRawEncoding(PTI.UnalignedQualLoc));
return;
}
@@ -2586,7 +2768,8 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
D.getDeclSpec().getConstSpecLoc(),
D.getDeclSpec().getVolatileSpecLoc(),
D.getDeclSpec().getRestrictSpecLoc(),
- D.getDeclSpec().getAtomicSpecLoc());
+ D.getDeclSpec().getAtomicSpecLoc(),
+ D.getDeclSpec().getUnalignedSpecLoc());
}
static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
@@ -2700,6 +2883,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case Declarator::FileContext:
case Declarator::BlockContext:
case Declarator::ForContext:
+ case Declarator::InitStmtContext:
case Declarator::ConditionContext:
break;
case Declarator::CXXNewContext:
@@ -2785,6 +2969,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case Declarator::MemberContext:
case Declarator::BlockContext:
case Declarator::ForContext:
+ case Declarator::InitStmtContext:
case Declarator::BlockLiteralContext:
case Declarator::LambdaExprContext:
// C++11 [dcl.type]p3:
@@ -2940,6 +3125,26 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D,
unsigned ChunkIndex) {
assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function);
+ // Check for an explicit CC attribute.
+ for (auto Attr = FTI.AttrList; Attr; Attr = Attr->getNext()) {
+ switch (Attr->getKind()) {
+ CALLING_CONV_ATTRS_CASELIST: {
+ // Ignore attributes that don't validate or can't apply to the
+ // function type. We'll diagnose the failure to apply them in
+ // handleFunctionTypeAttr.
+ CallingConv CC;
+ if (!S.CheckCallingConvAttr(*Attr, CC) &&
+ (!FTI.isVariadic || supportsVariadicCall(CC))) {
+ return CC;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
bool IsCXXInstanceMethod = false;
if (S.getLangOpts().CPlusPlus) {
@@ -2979,15 +3184,19 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D,
CallingConv CC = S.Context.getDefaultCallingConvention(FTI.isVariadic,
IsCXXInstanceMethod);
- // Attribute AT_OpenCLKernel affects the calling convention only on
- // the SPIR target, hence it cannot be treated as a calling
+ // Attribute AT_OpenCLKernel affects the calling convention for SPIR
+ // and AMDGPU targets, hence it cannot be treated as a calling
// convention attribute. This is the simplest place to infer
- // "spir_kernel" for OpenCL kernels on SPIR.
- if (CC == CC_SpirFunction) {
+ // calling convention for OpenCL kernels.
+ if (S.getLangOpts().OpenCL) {
for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
Attr; Attr = Attr->getNext()) {
if (Attr->getKind() == AttributeList::AT_OpenCLKernel) {
- CC = CC_SpirKernel;
+ llvm::Triple::ArchType arch = S.Context.getTargetInfo().getTriple().getArch();
+ if (arch == llvm::Triple::spir || arch == llvm::Triple::spir64 ||
+ arch == llvm::Triple::amdgcn) {
+ CC = CC_OpenCLKernel;
+ }
break;
}
}
@@ -3004,7 +3213,7 @@ namespace {
BlockPointer,
MemberPointer,
};
-}
+} // end anonymous namespace
IdentifierInfo *Sema::getNullabilityKeyword(NullabilityKind nullability) {
switch (nullability) {
@@ -3064,7 +3273,7 @@ namespace {
// NSError**
NSErrorPointerPointer,
};
-}
+} // end anonymous namespace
/// Classify the given declarator, whose type-specified is \c type, based on
/// what kind of pointer it refers to.
@@ -3192,7 +3401,6 @@ static PointerDeclaratorKind classifyPointerDeclarator(Sema &S,
break;
} while (true);
-
switch (numNormalPointers) {
case 0:
return PointerDeclaratorKind::NonPointer;
@@ -3509,6 +3717,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case Declarator::CXXCatchContext:
case Declarator::CXXNewContext:
case Declarator::ForContext:
+ case Declarator::InitStmtContext:
case Declarator::LambdaExprContext:
case Declarator::LambdaExprParameterContext:
case Declarator::ObjCCatchContext:
@@ -3609,15 +3818,20 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case DeclaratorChunk::BlockPointer:
// If blocks are disabled, emit an error.
if (!LangOpts.Blocks)
- S.Diag(DeclType.Loc, diag::err_blocks_disable);
+ S.Diag(DeclType.Loc, diag::err_blocks_disable) << LangOpts.OpenCL;
// Handle pointer nullability.
inferPointerNullability(SimplePointerKind::BlockPointer,
DeclType.Loc, DeclType.getAttrListRef());
T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
- if (DeclType.Cls.TypeQuals)
+ if (DeclType.Cls.TypeQuals || LangOpts.OpenCL) {
+ // OpenCL v2.0, s6.12.5 - Block variable declarations are implicitly
+ // qualified with const.
+ if (LangOpts.OpenCL)
+ DeclType.Cls.TypeQuals |= DeclSpec::TQ_const;
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals);
+ }
break;
case DeclaratorChunk::Pointer:
// Verify that we're not building a pointer to pointer to function with
@@ -3638,10 +3852,21 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
break;
}
+
+ // OpenCL v2.0 s6.9b - Pointer to image/sampler cannot be used.
+ // OpenCL v2.0 s6.13.16.1 - Pointer to pipe cannot be used.
+ // OpenCL v2.0 s6.12.5 - Pointers to Blocks are not allowed.
+ if (LangOpts.OpenCL) {
+ if (T->isImageType() || T->isSamplerT() || T->isPipeType() ||
+ T->isBlockPointerType()) {
+ S.Diag(D.getIdentifierLoc(), diag::err_opencl_pointer_to_type) << T;
+ D.setInvalidType(true);
+ }
+ }
+
T = S.BuildPointerType(T, DeclType.Loc, Name);
if (DeclType.Ptr.TypeQuals)
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
-
break;
case DeclaratorChunk::Reference: {
// Verify that we're not building a reference to pointer to function with
@@ -3808,7 +4033,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (T->isHalfType()) {
if (S.getLangOpts().OpenCL) {
if (!S.getOpenCLOptions().cl_khr_fp16) {
- S.Diag(D.getIdentifierLoc(), diag::err_opencl_half_return) << T;
+ S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
+ << T << 0 /*pointer hint*/;
D.setInvalidType(true);
}
} else if (!S.getLangOpts().HalfArgsAndReturns) {
@@ -3818,6 +4044,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
+ // OpenCL v2.0 s6.12.5 - A block cannot be the return value of a
+ // function.
+ if (LangOpts.OpenCL && (T->isBlockPointerType() || T->isImageType() ||
+ T->isSamplerT() || T->isPipeType())) {
+ S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
+ << T << 1 /*hint off*/;
+ D.setInvalidType(true);
+ }
+
// Methods cannot return interface types. All ObjC objects are
// passed by reference.
if (T->isObjCObjectType()) {
@@ -3967,9 +4202,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
SmallVector<QualType, 16> ParamTys;
ParamTys.reserve(FTI.NumParams);
- SmallVector<bool, 16> ConsumedParameters;
- ConsumedParameters.reserve(FTI.NumParams);
- bool HasAnyConsumedParameters = false;
+ SmallVector<FunctionProtoType::ExtParameterInfo, 16>
+ ExtParameterInfos(FTI.NumParams);
+ bool HasAnyInterestingExtParameterInfos = false;
for (unsigned i = 0, e = FTI.NumParams; i != e; ++i) {
ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
@@ -4027,17 +4262,25 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
- if (LangOpts.ObjCAutoRefCount) {
- bool Consumed = Param->hasAttr<NSConsumedAttr>();
- ConsumedParameters.push_back(Consumed);
- HasAnyConsumedParameters |= Consumed;
+ if (LangOpts.ObjCAutoRefCount && Param->hasAttr<NSConsumedAttr>()) {
+ ExtParameterInfos[i] = ExtParameterInfos[i].withIsConsumed(true);
+ HasAnyInterestingExtParameterInfos = true;
+ }
+
+ if (auto attr = Param->getAttr<ParameterABIAttr>()) {
+ ExtParameterInfos[i] =
+ ExtParameterInfos[i].withABI(attr->getABI());
+ HasAnyInterestingExtParameterInfos = true;
}
ParamTys.push_back(ParamTy);
}
- if (HasAnyConsumedParameters)
- EPI.ConsumedParameters = ConsumedParameters.data();
+ if (HasAnyInterestingExtParameterInfos) {
+ EPI.ExtParameterInfos = ExtParameterInfos.data();
+ checkExtParameterInfos(S, ParamTys, EPI,
+ [&](unsigned i) { return FTI.Params[i].Param->getLocation(); });
+ }
SmallVector<QualType, 4> Exceptions;
SmallVector<ParsedType, 2> DynamicExceptions;
@@ -4068,7 +4311,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
T = Context.getFunctionType(T, ParamTys, EPI);
}
-
break;
}
case DeclaratorChunk::MemberPointer: {
@@ -4306,6 +4548,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case Declarator::MemberContext:
case Declarator::BlockContext:
case Declarator::ForContext:
+ case Declarator::InitStmtContext:
case Declarator::ConditionContext:
case Declarator::CXXCatchContext:
case Declarator::ObjCCatchContext:
@@ -4497,6 +4740,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
return AttributeList::AT_ThisCall;
case AttributedType::attr_pascal:
return AttributeList::AT_Pascal;
+ case AttributedType::attr_swiftcall:
+ return AttributeList::AT_SwiftCall;
case AttributedType::attr_vectorcall:
return AttributeList::AT_VectorCall;
case AttributedType::attr_pcs:
@@ -4508,6 +4753,10 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
return AttributeList::AT_MSABI;
case AttributedType::attr_sysv_abi:
return AttributeList::AT_SysVABI;
+ case AttributedType::attr_preserve_most:
+ return AttributeList::AT_PreserveMost;
+ case AttributedType::attr_preserve_all:
+ return AttributeList::AT_PreserveAll;
case AttributedType::attr_ptr32:
return AttributeList::AT_Ptr32;
case AttributedType::attr_ptr64:
@@ -4725,7 +4974,7 @@ namespace {
void VisitPipeTypeLoc(PipeTypeLoc TL) {
TL.setKWLoc(DS.getTypeSpecTypeLoc());
- TypeSourceInfo *TInfo = 0;
+ TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
}
@@ -4859,7 +5108,7 @@ namespace {
llvm_unreachable("unsupported TypeLoc kind in declarator!");
}
};
-}
+} // end anonymous namespace
static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) {
SourceLocation Loc;
@@ -4995,7 +5244,6 @@ ParsedType Sema::ActOnObjCInstanceType(SourceLocation Loc) {
return CreateParsedType(T, TInfo);
}
-
//===----------------------------------------------------------------------===//
// Type Attribute Processing
//===----------------------------------------------------------------------===//
@@ -5194,11 +5442,13 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
}
// Otherwise, if the qualifiers actually conflict, pull sugar off
- // until we reach a type that is directly qualified.
+ // and remove the ObjCLifetime qualifiers.
if (previousLifetime != lifetime) {
- // This should always terminate: the canonical type is
- // qualified, so some bit of sugar must be hiding it.
- while (!underlyingType.Quals.hasObjCLifetime()) {
+ // It's possible to have multiple local ObjCLifetime qualifiers. We
+ // can't stop after we reach a type that is directly qualified.
+ const Type *prevTy = nullptr;
+ while (!prevTy || prevTy != underlyingType.Ty) {
+ prevTy = underlyingType.Ty;
underlyingType = underlyingType.getSingleStepDesugaredType();
}
underlyingType.Quals.removeObjCLifetime();
@@ -5369,6 +5619,7 @@ namespace {
struct FunctionTypeUnwrapper {
enum WrapKind {
Desugar,
+ Attributed,
Parens,
Pointer,
BlockPointer,
@@ -5401,6 +5652,9 @@ namespace {
} else if (isa<ReferenceType>(Ty)) {
T = cast<ReferenceType>(Ty)->getPointeeType();
Stack.push_back(Reference);
+ } else if (isa<AttributedType>(Ty)) {
+ T = cast<AttributedType>(Ty)->getEquivalentType();
+ Stack.push_back(Attributed);
} else {
const Type *DTy = Ty->getUnqualifiedDesugaredType();
if (Ty == DTy) {
@@ -5449,6 +5703,9 @@ namespace {
// information.
return wrap(C, Old->getUnqualifiedDesugaredType(), I);
+ case Attributed:
+ return wrap(C, cast<AttributedType>(Old)->getEquivalentType(), I);
+
case Parens: {
QualType New = wrap(C, cast<ParenType>(Old)->getInnerType(), I);
return C.getParenType(New);
@@ -5483,7 +5740,7 @@ namespace {
llvm_unreachable("unknown wrapping kind");
}
};
-}
+} // end anonymous namespace
static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
AttributeList &Attr,
@@ -5672,10 +5929,11 @@ bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
// Rebuild the "equivalent" type, which pushes __kindof down into
// the object type.
- QualType equivType = Context.getObjCObjectType(objType->getBaseType(),
- objType->getTypeArgsAsWritten(),
- objType->getProtocols(),
- /*isKindOf=*/true);
+ // There is no need to apply kindof on an unqualified id type.
+ QualType equivType = Context.getObjCObjectType(
+ objType->getBaseType(), objType->getTypeArgsAsWritten(),
+ objType->getProtocols(),
+ /*isKindOf=*/objType->isObjCUnqualifiedId() ? false : true);
// If we started with an object pointer type, rebuild it.
if (ptrType) {
@@ -5814,6 +6072,8 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
return AttributedType::attr_thiscall;
case AttributeList::AT_Pascal:
return AttributedType::attr_pascal;
+ case AttributeList::AT_SwiftCall:
+ return AttributedType::attr_swiftcall;
case AttributeList::AT_VectorCall:
return AttributedType::attr_vectorcall;
case AttributeList::AT_Pcs: {
@@ -5835,6 +6095,10 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
return AttributedType::attr_ms_abi;
case AttributeList::AT_SysVABI:
return AttributedType::attr_sysv_abi;
+ case AttributeList::AT_PreserveMost:
+ return AttributedType::attr_preserve_most;
+ case AttributeList::AT_PreserveAll:
+ return AttributedType::attr_preserve_all;
}
llvm_unreachable("unexpected attribute kind!");
}
@@ -5930,18 +6194,28 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
}
}
- // Diagnose use of callee-cleanup calling convention on variadic functions.
+ // Diagnose use of variadic functions with calling conventions that
+ // don't support them (e.g. because they're callee-cleanup).
+ // We delay warning about this on unprototyped function declarations
+ // until after redeclaration checking, just in case we pick up a
+ // prototype that way. And apparently we also "delay" warning about
+ // unprototyped function types in general, despite not necessarily having
+ // much ability to diagnose it later.
if (!supportsVariadicCall(CC)) {
const FunctionProtoType *FnP = dyn_cast<FunctionProtoType>(fn);
if (FnP && FnP->isVariadic()) {
unsigned DiagID = diag::err_cconv_varargs;
+
// stdcall and fastcall are ignored with a warning for GCC and MS
// compatibility.
- if (CC == CC_X86StdCall || CC == CC_X86FastCall)
+ bool IsInvalid = true;
+ if (CC == CC_X86StdCall || CC == CC_X86FastCall) {
DiagID = diag::warn_cconv_varargs;
+ IsInvalid = false;
+ }
S.Diag(attr.getLoc(), DiagID) << FunctionType::getNameForCallConv(CC);
- attr.setInvalid();
+ if (IsInvalid) attr.setInvalid();
return true;
}
}
@@ -5957,9 +6231,14 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
// Modify the CC from the wrapped function type, wrap it all back, and then
// wrap the whole thing in an AttributedType as written. The modified type
// might have a different CC if we ignored the attribute.
- FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC);
- QualType Equivalent =
+ QualType Equivalent;
+ if (CCOld == CC) {
+ Equivalent = type;
+ } else {
+ auto EI = unwrapped.get()->getExtInfo().withCallingConv(CC);
+ Equivalent =
unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ }
type = S.Context.getAttributedType(CCAttrKind, type, Equivalent);
return true;
}
@@ -6217,6 +6496,36 @@ static void HandleNeonVectorTypeAttr(QualType& CurType,
CurType = S.Context.getVectorType(CurType, numElts, VecKind);
}
+/// Handle OpenCL Access Qualifier Attribute.
+static void HandleOpenCLAccessAttr(QualType &CurType, const AttributeList &Attr,
+ Sema &S) {
+ // OpenCL v2.0 s6.6 - Access qualifier can be used only for image and pipe type.
+ if (!(CurType->isImageType() || CurType->isPipeType())) {
+ S.Diag(Attr.getLoc(), diag::err_opencl_invalid_access_qualifier);
+ Attr.setInvalid();
+ return;
+ }
+
+ if (const TypedefType* TypedefTy = CurType->getAs<TypedefType>()) {
+ QualType PointeeTy = TypedefTy->desugar();
+ S.Diag(Attr.getLoc(), diag::err_opencl_multiple_access_qualifiers);
+
+ std::string PrevAccessQual;
+ switch (cast<BuiltinType>(PointeeTy.getTypePtr())->getKind()) {
+ #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+ case BuiltinType::Id: \
+ PrevAccessQual = #Access; \
+ break;
+ #include "clang/Basic/OpenCLImageTypes.def"
+ default:
+ assert(0 && "Unable to find corresponding image type.");
+ }
+
+ S.Diag(TypedefTy->getDecl()->getLocStart(),
+ diag::note_opencl_typedef_access_qualifier) << PrevAccessQual;
+ }
+}
+
static void processTypeAttrs(TypeProcessingState &state, QualType &type,
TypeAttrLocation TAL, AttributeList *attrs) {
// Scan through and apply attributes to this type where it makes sense. Some
@@ -6312,9 +6621,8 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
VectorType::NeonPolyVector);
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_OpenCLImageAccess:
- // FIXME: there should be some type checking happening here, I would
- // imagine, but the original handler's checking was entirely superfluous.
+ case AttributeList::AT_OpenCLAccess:
+ HandleOpenCLAccessAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
@@ -6554,8 +6862,8 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
RD = Pattern;
D = RD->getDefinition();
} else if (auto *ED = dyn_cast<EnumDecl>(D)) {
- while (auto *NewED = ED->getInstantiatedFromMemberEnum())
- ED = NewED;
+ if (auto *Pattern = ED->getTemplateInstantiationPattern())
+ ED = Pattern;
if (OnlyNeedComplete && ED->isFixed()) {
// If the enum has a fixed underlying type, and we're only looking for a
// complete type (not a definition), any visible declaration of it will
@@ -6616,6 +6924,7 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
S.ImplicitMSInheritanceAttrLoc.isValid()
? S.ImplicitMSInheritanceAttrLoc
: RD->getSourceRange()));
+ S.Consumer.AssignInheritanceModel(RD);
}
}
@@ -6641,9 +6950,16 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
}
}
- // If we have a complete type, we're done.
NamedDecl *Def = nullptr;
- if (!T->isIncompleteType(&Def)) {
+ bool Incomplete = T->isIncompleteType(&Def);
+
+ // Check that any necessary explicit specializations are visible. For an
+ // enum, we just need the declaration, so don't check this.
+ if (Def && !isa<EnumDecl>(Def))
+ checkSpecializationVisibility(Loc, Def);
+
+ // If we have a complete type, we're done.
+ if (!Incomplete) {
// If we know about the definition but it is not visible, complain.
NamedDecl *SuggestedDef = nullptr;
if (Def &&
@@ -6652,7 +6968,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// definition visible.
bool TreatAsComplete = Diagnoser && !isSFINAEContext();
if (Diagnoser)
- diagnoseMissingImport(Loc, SuggestedDef, /*NeedDefinition*/true,
+ diagnoseMissingImport(Loc, SuggestedDef, MissingImportKind::Definition,
/*Recover*/TreatAsComplete);
return !TreatAsComplete;
}
@@ -6745,15 +7061,11 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
}
}
- if (!Diagnoser)
- return true;
+ // FIXME: If we didn't instantiate a definition because of an explicit
+ // specialization declaration, check that it's visible.
- // We have an incomplete type. Produce a diagnostic.
- if (Ident___float128 &&
- T == Context.getTypeDeclType(Context.getFloat128StubType())) {
- Diag(Loc, diag::err_typecheck_decl_incomplete_type___float128);
+ if (!Diagnoser)
return true;
- }
Diagnoser->diagnose(*this, Loc, T);