summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp810
1 files changed, 609 insertions, 201 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 0959f7d..aa7459d 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
@@ -33,8 +34,16 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
+#include "TypeLocBuilder.h"
+
using namespace clang;
+enum TypeDiagSelector {
+ TDS_Function,
+ TDS_Pointer,
+ TDS_ObjCObjOrBlock
+};
+
/// isOmittedBlockReturnType - Return true if this declarator is missing a
/// return type because this is a omitted return type on a block literal.
static bool isOmittedBlockReturnType(const Declarator &D) {
@@ -56,23 +65,15 @@ static bool isOmittedBlockReturnType(const Declarator &D) {
/// doesn't apply to the given type.
static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
QualType type) {
- bool useExpansionLoc = false;
-
- unsigned diagID = 0;
+ TypeDiagSelector WhichType;
+ bool useExpansionLoc = true;
switch (attr.getKind()) {
- case AttributeList::AT_ObjCGC:
- diagID = diag::warn_pointer_attribute_wrong_type;
- useExpansionLoc = true;
- break;
-
- case AttributeList::AT_ObjCOwnership:
- diagID = diag::warn_objc_object_attribute_wrong_type;
- useExpansionLoc = true;
- break;
-
+ case AttributeList::AT_ObjCGC: WhichType = TDS_Pointer; break;
+ case AttributeList::AT_ObjCOwnership: WhichType = TDS_ObjCObjOrBlock; break;
default:
// Assume everything else was a function attribute.
- diagID = diag::warn_function_attribute_wrong_type;
+ WhichType = TDS_Function;
+ useExpansionLoc = false;
break;
}
@@ -80,15 +81,17 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
StringRef name = attr.getName()->getName();
// The GC attributes are usually written with macros; special-case them.
- if (useExpansionLoc && loc.isMacroID() && attr.getParameterName()) {
- if (attr.getParameterName()->isStr("strong")) {
+ IdentifierInfo *II = attr.isArgIdent(0) ? attr.getArgAsIdent(0)->Ident : 0;
+ if (useExpansionLoc && loc.isMacroID() && II) {
+ if (II->isStr("strong")) {
if (S.findMacroSpelling(loc, "__strong")) name = "__strong";
- } else if (attr.getParameterName()->isStr("weak")) {
+ } else if (II->isStr("weak")) {
if (S.findMacroSpelling(loc, "__weak")) name = "__weak";
}
}
- S.Diag(loc, diagID) << name << type;
+ S.Diag(loc, diag::warn_type_attribute_wrong_type) << name << WhichType
+ << type;
}
// objc_gc applies to Objective-C pointers or, otherwise, to the
@@ -105,10 +108,19 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
case AttributeList::AT_StdCall: \
case AttributeList::AT_ThisCall: \
case AttributeList::AT_Pascal: \
+ case AttributeList::AT_MSABI: \
+ case AttributeList::AT_SysVABI: \
case AttributeList::AT_Regparm: \
case AttributeList::AT_Pcs: \
case AttributeList::AT_PnaclCall: \
- case AttributeList::AT_IntelOclBicc \
+ case AttributeList::AT_IntelOclBicc
+
+// Microsoft-specific type qualifiers.
+#define MS_TYPE_ATTRS_CASELIST \
+ case AttributeList::AT_Ptr32: \
+ case AttributeList::AT_Ptr64: \
+ case AttributeList::AT_SPtr: \
+ case AttributeList::AT_UPtr
namespace {
/// An object which stores processing state for the entire
@@ -223,26 +235,6 @@ namespace {
savedAttrs.back()->setNext(0);
}
};
-
- /// Basically std::pair except that we really want to avoid an
- /// implicit operator= for safety concerns. It's also a minor
- /// link-time optimization for this to be a private type.
- struct AttrAndList {
- /// The attribute.
- AttributeList &first;
-
- /// The head of the list the attribute is currently in.
- AttributeList *&second;
-
- AttrAndList(AttributeList &attr, AttributeList *&head)
- : first(attr), second(head) {}
- };
-}
-
-namespace llvm {
- template <> struct isPodLike<AttrAndList> {
- static const bool value = true;
- };
}
static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) {
@@ -292,6 +284,10 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
AttributeList &attr,
QualType &type);
+static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &state,
+ AttributeList &attr,
+ QualType &type);
+
static bool handleObjCGCTypeAttr(TypeProcessingState &state,
AttributeList &attr, QualType &type);
@@ -533,12 +529,7 @@ distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
return true;
}
- if (handleFunctionTypeAttr(state, attr, declSpecType)) {
- spliceAttrOutOfList(attr, attrList);
- return true;
- }
-
- return false;
+ return handleFunctionTypeAttr(state, attr, declSpecType);
}
/// A function type attribute was written in the decl spec. Try to
@@ -626,6 +617,10 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType);
break;
+ MS_TYPE_ATTRS_CASELIST:
+ // Microsoft type attributes cannot go after the declarator-id.
+ continue;
+
default:
break;
}
@@ -767,8 +762,13 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// is inferred from the return statements inside the block.
// The declspec is always missing in a lambda expr context; it is either
// specified with a trailing return type or inferred.
- if (declarator.getContext() == Declarator::LambdaExprContext ||
- isOmittedBlockReturnType(declarator)) {
+ if (S.getLangOpts().CPlusPlus1y &&
+ declarator.getContext() == Declarator::LambdaExprContext) {
+ // In C++1y, a lambda's implicit return type is 'auto'.
+ Result = Context.getAutoDeductType();
+ break;
+ } else if (declarator.getContext() == Declarator::LambdaExprContext ||
+ isOmittedBlockReturnType(declarator)) {
Result = Context.DependentTy;
break;
}
@@ -994,11 +994,54 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
case DeclSpec::TST_auto:
// TypeQuals handled by caller.
- Result = Context.getAutoType(QualType(), /*decltype(auto)*/false);
+ // If auto is mentioned in a lambda parameter context, convert it to a
+ // template parameter type immediately, with the appropriate depth and
+ // index, and update sema's state (LambdaScopeInfo) for the current lambda
+ // being analyzed (which tracks the invented type template parameter).
+ if (declarator.getContext() == Declarator::LambdaExprParameterContext) {
+ sema::LambdaScopeInfo *LSI = S.getCurLambda();
+ assert(LSI && "No LambdaScopeInfo on the stack!");
+ const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
+ const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
+ const bool IsParameterPack = declarator.hasEllipsis();
+
+ // Create a name for the invented template parameter type.
+ std::string InventedTemplateParamName = "$auto-";
+ llvm::raw_string_ostream ss(InventedTemplateParamName);
+ ss << TemplateParameterDepth;
+ ss << "-" << AutoParameterPosition;
+ ss.flush();
+
+ IdentifierInfo& TemplateParamII = Context.Idents.get(
+ InventedTemplateParamName.c_str());
+ // Turns out we must create the TemplateTypeParmDecl here to
+ // retrieve the corresponding template parameter type.
+ TemplateTypeParmDecl *CorrespondingTemplateParam =
+ TemplateTypeParmDecl::Create(Context,
+ // Temporarily add to the TranslationUnit DeclContext. When the
+ // associated TemplateParameterList is attached to a template
+ // declaration (such as FunctionTemplateDecl), the DeclContext
+ // for each template parameter gets updated appropriately via
+ // a call to AdoptTemplateParameterList.
+ Context.getTranslationUnitDecl(),
+ /*KeyLoc*/ SourceLocation(),
+ /*NameLoc*/ declarator.getLocStart(),
+ TemplateParameterDepth,
+ AutoParameterPosition, // our template param index
+ /* Identifier*/ &TemplateParamII, false, IsParameterPack);
+ LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
+ // Replace the 'auto' in the function parameter with this invented
+ // template type parameter.
+ Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0);
+ } else {
+ Result = Context.getAutoType(QualType(), /*decltype(auto)*/false, false);
+ }
break;
case DeclSpec::TST_decltype_auto:
- Result = Context.getAutoType(QualType(), /*decltype(auto)*/true);
+ Result = Context.getAutoType(QualType(),
+ /*decltype(auto)*/true,
+ /*IsDependent*/ false);
break;
case DeclSpec::TST_unknown_anytype:
@@ -1545,14 +1588,16 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
ASM = ArrayType::Normal;
}
} else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
- !T->isIncompleteType()) {
+ !T->isIncompleteType() && !T->isUndeducedType()) {
// Is the array too large?
unsigned ActiveSizeBits
= ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
- if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
+ if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
Diag(ArraySize->getLocStart(), diag::err_array_too_large)
<< ConstVal.toString(10)
<< ArraySize->getSourceRange();
+ return QualType();
+ }
}
T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
@@ -1567,7 +1612,6 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (!getLangOpts().C99) {
if (T->isVariableArrayType()) {
// Prohibit the use of non-POD types in VLAs.
- // FIXME: C++1y allows this.
QualType BaseT = Context.getBaseElementType(T);
if (!T->isDependentType() &&
!BaseT.isPODType(Context) &&
@@ -1583,9 +1627,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
}
// Just extwarn about VLAs.
else
- Diag(Loc, getLangOpts().CPlusPlus1y
- ? diag::warn_cxx11_compat_array_of_runtime_bound
- : diag::ext_vla);
+ Diag(Loc, diag::ext_vla);
} else if (ASM != ArrayType::Normal || Quals != 0)
Diag(Loc,
getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx
@@ -1616,8 +1658,9 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) {
llvm::APSInt vecSize(32);
if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) {
- Diag(AttrLoc, diag::err_attribute_argument_not_int)
- << "ext_vector_type" << ArraySize->getSourceRange();
+ Diag(AttrLoc, diag::err_attribute_argument_type)
+ << "ext_vector_type" << AANT_ArgumentIntegerConstant
+ << ArraySize->getSourceRange();
return QualType();
}
@@ -1631,30 +1674,50 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
return QualType();
}
+ if (VectorType::isVectorSizeTooLarge(vectorSize)) {
+ Diag(AttrLoc, diag::err_attribute_size_too_large)
+ << ArraySize->getSourceRange();
+ return QualType();
+ }
+
return Context.getExtVectorType(T, vectorSize);
}
return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc);
}
-QualType Sema::BuildFunctionType(QualType T,
- llvm::MutableArrayRef<QualType> ParamTypes,
- SourceLocation Loc, DeclarationName Entity,
- const FunctionProtoType::ExtProtoInfo &EPI) {
+bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) {
if (T->isArrayType() || T->isFunctionType()) {
Diag(Loc, diag::err_func_returning_array_function)
<< T->isFunctionType() << T;
- return QualType();
+ return true;
}
// Functions cannot return half FP.
if (T->isHalfType()) {
Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 <<
FixItHint::CreateInsertion(Loc, "*");
- return QualType();
+ return true;
}
+ // Methods cannot return interface types. All ObjC objects are
+ // passed by reference.
+ if (T->isObjCObjectType()) {
+ Diag(Loc, diag::err_object_cannot_be_passed_returned_by_value) << 0 << T;
+ return 0;
+ }
+
+ return false;
+}
+
+QualType Sema::BuildFunctionType(QualType T,
+ llvm::MutableArrayRef<QualType> ParamTypes,
+ SourceLocation Loc, DeclarationName Entity,
+ const FunctionProtoType::ExtProtoInfo &EPI) {
bool Invalid = false;
+
+ Invalid |= CheckFunctionReturnType(T, Loc);
+
for (unsigned Idx = 0, Cnt = ParamTypes.size(); Idx < Cnt; ++Idx) {
// FIXME: Loc is too inprecise here, should use proper locations for args.
QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]);
@@ -1749,6 +1812,8 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
}
}
+ // FIXME: Adjust member function pointer calling conventions.
+
return Context.getMemberPointerType(T, Class.getTypePtr());
}
@@ -1917,7 +1982,7 @@ static void diagnoseIgnoredQualifiers(
{ DeclSpec::TQ_atomic, "_Atomic", AtomicQualLoc }
};
- llvm::SmallString<32> QualStr;
+ SmallString<32> QualStr;
unsigned NumQuals = 0;
SourceLocation Loc;
FixItHint FixIts[4];
@@ -2062,6 +2127,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// In C++11, a function declarator using 'auto' must have a trailing return
// type (this is checked later) and we can skip this. In other languages
// using auto, we need to check regardless.
+ // C++14 In generic lambdas allow 'auto' in their parameters.
if (ContainsPlaceholderType &&
(!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) {
int Error = -1;
@@ -2074,7 +2140,12 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case Declarator::ObjCParameterContext:
case Declarator::ObjCResultContext:
case Declarator::PrototypeContext:
- Error = 0; // Function prototype
+ Error = 0;
+ break;
+ case Declarator::LambdaExprParameterContext:
+ if (!(SemaRef.getLangOpts().CPlusPlus1y
+ && D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto))
+ Error = 14;
break;
case Declarator::MemberContext:
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
@@ -2154,8 +2225,10 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
AutoRange = D.getName().getSourceRange();
if (Error != -1) {
+ const bool IsDeclTypeAuto =
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_decltype_auto;
SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)
- << Error << AutoRange;
+ << IsDeclTypeAuto << Error << AutoRange;
T = SemaRef.Context.IntTy;
D.setInvalidType(true);
} else
@@ -2205,6 +2278,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
D.setInvalidType(true);
break;
case Declarator::PrototypeContext:
+ case Declarator::LambdaExprParameterContext:
case Declarator::ObjCParameterContext:
case Declarator::ObjCResultContext:
case Declarator::KNRTypeListContext:
@@ -2375,7 +2449,8 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
S.Diag(DeclType.Loc, diag::note_empty_parens_default_ctor)
<< FixItHint::CreateRemoval(ParenRange);
else {
- std::string Init = S.getFixItZeroInitializerForType(RT);
+ std::string Init =
+ S.getFixItZeroInitializerForType(RT, ParenRange.getBegin());
if (Init.empty() && S.LangOpts.CPlusPlus11)
Init = "{}";
if (!Init.empty())
@@ -2385,6 +2460,52 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
}
}
+/// Helper for figuring out the default CC for a function declarator type. If
+/// this is the outermost chunk, then we can determine the CC from the
+/// declarator context. If not, then this could be either a member function
+/// type or normal function type.
+static CallingConv
+getCCForDeclaratorChunk(Sema &S, Declarator &D,
+ const DeclaratorChunk::FunctionTypeInfo &FTI,
+ unsigned ChunkIndex) {
+ assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function);
+
+ bool IsCXXInstanceMethod = false;
+
+ if (S.getLangOpts().CPlusPlus) {
+ // Look inwards through parentheses to see if this chunk will form a
+ // member pointer type or if we're the declarator. Any type attributes
+ // between here and there will override the CC we choose here.
+ unsigned I = ChunkIndex;
+ bool FoundNonParen = false;
+ while (I && !FoundNonParen) {
+ --I;
+ if (D.getTypeObject(I).Kind != DeclaratorChunk::Paren)
+ FoundNonParen = true;
+ }
+
+ if (FoundNonParen) {
+ // If we're not the declarator, we're a regular function type unless we're
+ // in a member pointer.
+ IsCXXInstanceMethod =
+ D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer;
+ } else {
+ // We're the innermost decl chunk, so must be a function declarator.
+ assert(D.isFunctionDeclarator());
+
+ // If we're inside a record, we're declaring a method, but it could be
+ // explicitly or implicitly static.
+ IsCXXInstanceMethod =
+ D.isFirstDeclarationOfMember() &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+ !D.isStaticMember();
+ }
+ }
+
+ return S.Context.getDefaultCallingConvention(FTI.isVariadic,
+ IsCXXInstanceMethod);
+}
+
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType declSpecType,
TypeSourceInfo *TInfo) {
@@ -2578,8 +2699,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
}
-
- if (const AutoType *AT = T->getContainedAutoType()) {
+ const AutoType *AT = T->getContainedAutoType();
+ // Allow arrays of auto if we are a generic lambda parameter.
+ // i.e. [](auto (&array)[5]) { return array[0]; }; OK
+ if (AT && D.getContext() != Declarator::LambdaExprParameterContext) {
// We've already diagnosed this for decltype(auto).
if (!AT->isDecltypeAuto())
S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
@@ -2665,6 +2788,33 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
+ // Methods cannot return interface types. All ObjC objects are
+ // passed by reference.
+ if (T->isObjCObjectType()) {
+ SourceLocation DiagLoc, FixitLoc;
+ if (TInfo) {
+ DiagLoc = TInfo->getTypeLoc().getLocStart();
+ FixitLoc = S.PP.getLocForEndOfToken(TInfo->getTypeLoc().getLocEnd());
+ } else {
+ DiagLoc = D.getDeclSpec().getTypeSpecTypeLoc();
+ FixitLoc = S.PP.getLocForEndOfToken(D.getDeclSpec().getLocEnd());
+ }
+ S.Diag(DiagLoc, diag::err_object_cannot_be_passed_returned_by_value)
+ << 0 << T
+ << FixItHint::CreateInsertion(FixitLoc, "*");
+
+ T = Context.getObjCObjectPointerType(T);
+ if (TInfo) {
+ TypeLocBuilder TLB;
+ TLB.pushFullCopy(TInfo->getTypeLoc());
+ ObjCObjectPointerTypeLoc TLoc = TLB.push<ObjCObjectPointerTypeLoc>(T);
+ TLoc.setStarLoc(FixitLoc);
+ TInfo = TLB.getTypeSourceInfo(Context, T);
+ }
+
+ D.setInvalidType(true);
+ }
+
// cv-qualifiers on return types are pointless except when the type is a
// class type in C++.
if ((T.getCVRQualifiers() || T->isAtomicType()) &&
@@ -2710,13 +2860,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
- if (LangOpts.CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
+ if (LangOpts.CPlusPlus && D.getDeclSpec().hasTagDefinition()) {
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
- if (Tag->isCompleteDefinition())
- S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
- << Context.getTypeDeclType(Tag);
+ S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
+ << Context.getTypeDeclType(Tag);
}
// Exception specs are not allowed in typedefs. Complain, but add it
@@ -2731,9 +2880,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (FTI.isAmbiguous)
warnAboutAmbiguousFunction(S, D, DeclType, T);
+ FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex));
+
if (!FTI.NumArgs && !FTI.isVariadic && !LangOpts.CPlusPlus) {
// Simple void foo(), where the incoming T is the result type.
- T = Context.getFunctionNoProtoType(T);
+ T = Context.getFunctionNoProtoType(T, EI);
} else {
// We allow a zero-parameter variadic function in C if the
// function is marked with the "overloadable" attribute. Scan
@@ -2758,11 +2909,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
S.Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
D.setInvalidType(true);
// Recover by creating a K&R-style function type.
- T = Context.getFunctionNoProtoType(T);
+ T = Context.getFunctionNoProtoType(T, EI);
break;
}
FunctionProtoType::ExtProtoInfo EPI;
+ EPI.ExtInfo = EI;
EPI.Variadic = FTI.isVariadic;
EPI.HasTrailingReturn = FTI.hasTrailingReturnType();
EPI.TypeQuals = FTI.TypeQuals;
@@ -2784,10 +2936,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType ArgTy = Param->getType();
assert(!ArgTy.isNull() && "Couldn't parse type?");
- // Adjust the parameter type.
- assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) &&
- "Unadjusted type?");
-
// Look for 'void'. void is allowed only as a single argument to a
// function with no other parameters (C99 6.7.5.3p10). We record
// int(void) as a FunctionProtoType with an empty argument list.
@@ -3017,9 +3165,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
EPI.TypeQuals = 0;
EPI.RefQualifier = RQ_None;
- T = Context.getFunctionType(FnTy->getResultType(),
- ArrayRef<QualType>(FnTy->arg_type_begin(),
- FnTy->getNumArgs()),
+ T = Context.getFunctionType(FnTy->getResultType(), FnTy->getArgTypes(),
EPI);
// Rebuild any parens around the identifier in the function type.
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
@@ -3054,6 +3200,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// is a parameter pack (14.5.3). [...]
switch (D.getContext()) {
case Declarator::PrototypeContext:
+ case Declarator::LambdaExprParameterContext:
// C++0x [dcl.fct]p13:
// [...] When it is part of a parameter-declaration-clause, the
// parameter pack is a function parameter pack (14.5.3). The type T
@@ -3072,7 +3219,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
T = Context.getPackExpansionType(T, None);
}
break;
-
case Declarator::TemplateParamContext:
// C++0x [temp.param]p15:
// If a template-parameter is a [...] is a parameter-declaration that
@@ -3181,13 +3327,18 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
case Qualifiers::OCL_Autoreleasing: attrStr = "autoreleasing"; break;
}
+ IdentifierLoc *Arg = new (S.Context) IdentifierLoc;
+ Arg->Ident = &S.Context.Idents.get(attrStr);
+ Arg->Loc = SourceLocation();
+
+ ArgsUnion Args(Arg);
+
// If there wasn't one, add one (with an invalid source location
// so that we don't make an AttributedType for it).
AttributeList *attr = D.getAttributePool()
.create(&S.Context.Idents.get("objc_ownership"), SourceLocation(),
/*scope*/ 0, SourceLocation(),
- &S.Context.Idents.get(attrStr), SourceLocation(),
- /*args*/ 0, 0, AttributeList::AS_GNU);
+ /*args*/ &Args, 1, AttributeList::AS_GNU);
spliceAttrIntoList(*attr, chunk.getAttrListRef());
// TODO: mark whether we did this inference?
@@ -3291,11 +3442,24 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
case AttributedType::attr_pascal:
return AttributeList::AT_Pascal;
case AttributedType::attr_pcs:
+ case AttributedType::attr_pcs_vfp:
return AttributeList::AT_Pcs;
case AttributedType::attr_pnaclcall:
return AttributeList::AT_PnaclCall;
case AttributedType::attr_inteloclbicc:
return AttributeList::AT_IntelOclBicc;
+ case AttributedType::attr_ms_abi:
+ return AttributeList::AT_MSABI;
+ case AttributedType::attr_sysv_abi:
+ return AttributeList::AT_SysVABI;
+ case AttributedType::attr_ptr32:
+ return AttributeList::AT_Ptr32;
+ case AttributedType::attr_ptr64:
+ return AttributeList::AT_Ptr64;
+ case AttributedType::attr_sptr:
+ return AttributeList::AT_SPtr;
+ case AttributedType::attr_uptr:
+ return AttributeList::AT_UPtr;
}
llvm_unreachable("unexpected attribute kind!");
}
@@ -3312,10 +3476,10 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL,
}
TL.setAttrNameLoc(attrs->getLoc());
- if (TL.hasAttrExprOperand())
- TL.setAttrExprOperand(attrs->getArg(0));
- else if (TL.hasAttrEnumOperand())
- TL.setAttrEnumOperandLoc(attrs->getParameterLoc());
+ if (TL.hasAttrExprOperand() && attrs->isArgExpr(0))
+ TL.setAttrExprOperand(attrs->getArgAsExpr(0));
+ else if (TL.hasAttrEnumOperand() && attrs->isArgIdent(0))
+ TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc);
// FIXME: preserve this information to here.
if (TL.hasAttrOperand())
@@ -3393,9 +3557,11 @@ namespace {
TemplateSpecializationTypeLoc NamedTL = ElabTL.getNamedTypeLoc()
.castAs<TemplateSpecializationTypeLoc>();
TL.copy(NamedTL);
- }
- else
+ } else {
TL.copy(OldTL.castAs<TemplateSpecializationTypeLoc>());
+ assert(TL.getRAngleLoc() == OldTL.castAs<TemplateSpecializationTypeLoc>().getRAngleLoc());
+ }
+
}
void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
@@ -3509,6 +3675,9 @@ namespace {
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
llvm_unreachable("qualified type locs not expected here!");
}
+ void VisitDecayedTypeLoc(DecayedTypeLoc TL) {
+ llvm_unreachable("decayed type locs not expected here!");
+ }
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
fillAttributedTypeLoc(TL, Chunk.getAttrs());
@@ -3769,15 +3938,17 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
Attr.setInvalid();
return;
}
- Expr *ASArgExpr = static_cast<Expr *>(Attr.getArg(0));
+ Expr *ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
llvm::APSInt addrSpace(32);
if (ASArgExpr->isTypeDependent() || ASArgExpr->isValueDependent() ||
!ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_space_not_int)
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
<< ASArgExpr->getSourceRange();
Attr.setInvalid();
return;
@@ -3797,7 +3968,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
max = Qualifiers::MaxAddressSpace;
if (addrSpace > max) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
- << Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange();
+ << int(Qualifiers::MaxAddressSpace) << ASArgExpr->getSourceRange();
Attr.setInvalid();
return;
}
@@ -3872,9 +4043,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
if (AttrLoc.isMacroID())
AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first;
- if (!attr.getParameterName()) {
- S.Diag(AttrLoc, diag::err_attribute_argument_n_not_string)
- << "objc_ownership" << 1;
+ if (!attr.isArgIdent(0)) {
+ S.Diag(AttrLoc, diag::err_attribute_argument_type)
+ << attr.getName() << AANT_ArgumentString;
attr.setInvalid();
return true;
}
@@ -3884,18 +4055,19 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
if (!S.getLangOpts().ObjCAutoRefCount)
return true;
+ IdentifierInfo *II = attr.getArgAsIdent(0)->Ident;
Qualifiers::ObjCLifetime lifetime;
- if (attr.getParameterName()->isStr("none"))
+ if (II->isStr("none"))
lifetime = Qualifiers::OCL_ExplicitNone;
- else if (attr.getParameterName()->isStr("strong"))
+ else if (II->isStr("strong"))
lifetime = Qualifiers::OCL_Strong;
- else if (attr.getParameterName()->isStr("weak"))
+ else if (II->isStr("weak"))
lifetime = Qualifiers::OCL_Weak;
- else if (attr.getParameterName()->isStr("autoreleasing"))
+ else if (II->isStr("autoreleasing"))
lifetime = Qualifiers::OCL_Autoreleasing;
else {
S.Diag(AttrLoc, diag::warn_attribute_type_not_supported)
- << "objc_ownership" << attr.getParameterName();
+ << attr.getName() << II;
attr.setInvalid();
return true;
}
@@ -3936,8 +4108,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
case Qualifiers::OCL_Weak: name = "__weak"; break;
case Qualifiers::OCL_Autoreleasing: name = "__autoreleasing"; break;
}
- S.Diag(AttrLoc, diag::warn_objc_object_attribute_wrong_type)
- << name << type;
+ S.Diag(AttrLoc, diag::warn_type_attribute_wrong_type) << name
+ << TDS_ObjCObjOrBlock << type;
}
QualType origType = type;
@@ -4006,27 +4178,30 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state,
attr.setInvalid();
return true;
}
-
+
// Check the attribute arguments.
- if (!attr.getParameterName()) {
- S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
- << "objc_gc" << 1;
+ if (!attr.isArgIdent(0)) {
+ S.Diag(attr.getLoc(), diag::err_attribute_argument_type)
+ << attr.getName() << AANT_ArgumentString;
attr.setInvalid();
return true;
}
Qualifiers::GC GCAttr;
- if (attr.getNumArgs() != 0) {
- S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ if (attr.getNumArgs() > 1) {
+ S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << attr.getName() << 1;
attr.setInvalid();
return true;
}
- if (attr.getParameterName()->isStr("weak"))
+
+ IdentifierInfo *II = attr.getArgAsIdent(0)->Ident;
+ if (II->isStr("weak"))
GCAttr = Qualifiers::Weak;
- else if (attr.getParameterName()->isStr("strong"))
+ else if (II->isStr("strong"))
GCAttr = Qualifiers::Strong;
else {
S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported)
- << "objc_gc" << attr.getParameterName();
+ << attr.getName() << II;
attr.setInvalid();
return true;
}
@@ -4172,6 +4347,109 @@ namespace {
};
}
+static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
+ AttributeList &Attr,
+ QualType &Type) {
+ Sema &S = State.getSema();
+
+ AttributeList::Kind Kind = Attr.getKind();
+ QualType Desugared = Type;
+ const AttributedType *AT = dyn_cast<AttributedType>(Type);
+ while (AT) {
+ AttributedType::Kind CurAttrKind = AT->getAttrKind();
+
+ // You cannot specify duplicate type attributes, so if the attribute has
+ // already been applied, flag it.
+ if (getAttrListKind(CurAttrKind) == Kind) {
+ S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact)
+ << Attr.getName();
+ return true;
+ }
+
+ // You cannot have both __sptr and __uptr on the same type, nor can you
+ // have __ptr32 and __ptr64.
+ if ((CurAttrKind == AttributedType::attr_ptr32 &&
+ Kind == AttributeList::AT_Ptr64) ||
+ (CurAttrKind == AttributedType::attr_ptr64 &&
+ Kind == AttributeList::AT_Ptr32)) {
+ S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << "'__ptr32'" << "'__ptr64'";
+ return true;
+ } else if ((CurAttrKind == AttributedType::attr_sptr &&
+ Kind == AttributeList::AT_UPtr) ||
+ (CurAttrKind == AttributedType::attr_uptr &&
+ Kind == AttributeList::AT_SPtr)) {
+ S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << "'__sptr'" << "'__uptr'";
+ return true;
+ }
+
+ Desugared = AT->getEquivalentType();
+ AT = dyn_cast<AttributedType>(Desugared);
+ }
+
+ // Pointer type qualifiers can only operate on pointer types, but not
+ // pointer-to-member types.
+ if (!isa<PointerType>(Desugared)) {
+ S.Diag(Attr.getLoc(), Type->isMemberPointerType() ?
+ diag::err_attribute_no_member_pointers :
+ diag::err_attribute_pointers_only) << Attr.getName();
+ return true;
+ }
+
+ AttributedType::Kind TAK;
+ switch (Kind) {
+ default: llvm_unreachable("Unknown attribute kind");
+ case AttributeList::AT_Ptr32: TAK = AttributedType::attr_ptr32; break;
+ case AttributeList::AT_Ptr64: TAK = AttributedType::attr_ptr64; break;
+ case AttributeList::AT_SPtr: TAK = AttributedType::attr_sptr; break;
+ case AttributeList::AT_UPtr: TAK = AttributedType::attr_uptr; break;
+ }
+
+ Type = S.Context.getAttributedType(TAK, Type, Type);
+ return false;
+}
+
+static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
+ assert(!Attr.isInvalid());
+ switch (Attr.getKind()) {
+ default:
+ llvm_unreachable("not a calling convention attribute");
+ case AttributeList::AT_CDecl:
+ return AttributedType::attr_cdecl;
+ case AttributeList::AT_FastCall:
+ return AttributedType::attr_fastcall;
+ case AttributeList::AT_StdCall:
+ return AttributedType::attr_stdcall;
+ case AttributeList::AT_ThisCall:
+ return AttributedType::attr_thiscall;
+ case AttributeList::AT_Pascal:
+ return AttributedType::attr_pascal;
+ case AttributeList::AT_Pcs: {
+ // The attribute may have had a fixit applied where we treated an
+ // identifier as a string literal. The contents of the string are valid,
+ // but the form may not be.
+ StringRef Str;
+ if (Attr.isArgExpr(0))
+ Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString();
+ else
+ Str = Attr.getArgAsIdent(0)->Ident->getName();
+ return llvm::StringSwitch<AttributedType::Kind>(Str)
+ .Case("aapcs", AttributedType::attr_pcs)
+ .Case("aapcs-vfp", AttributedType::attr_pcs_vfp);
+ }
+ case AttributeList::AT_PnaclCall:
+ return AttributedType::attr_pnaclcall;
+ case AttributeList::AT_IntelOclBicc:
+ return AttributedType::attr_inteloclbicc;
+ case AttributeList::AT_MSABI:
+ return AttributedType::attr_ms_abi;
+ case AttributeList::AT_SysVABI:
+ return AttributedType::attr_sysv_abi;
+ }
+ llvm_unreachable("unexpected attribute kind!");
+}
+
/// Process an individual function attribute. Returns true to
/// indicate that the attribute was handled, false if it wasn't.
static bool handleFunctionTypeAttr(TypeProcessingState &state,
@@ -4248,34 +4526,41 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
const FunctionType *fn = unwrapped.get();
CallingConv CCOld = fn->getCallConv();
- if (S.Context.getCanonicalCallConv(CC) ==
- S.Context.getCanonicalCallConv(CCOld)) {
- FunctionType::ExtInfo EI= unwrapped.get()->getExtInfo().withCallingConv(CC);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
- return true;
- }
+ AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr);
- if (CCOld != (S.LangOpts.MRTD ? CC_X86StdCall : CC_Default)) {
- // Should we diagnose reapplications of the same convention?
- S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
- << FunctionType::getNameForCallConv(CC)
- << FunctionType::getNameForCallConv(CCOld);
- attr.setInvalid();
- return true;
+ if (CCOld != CC) {
+ // Error out on when there's already an attribute on the type
+ // and the CCs don't match.
+ const AttributedType *AT = S.getCallingConvAttributedType(type);
+ if (AT && AT->getAttrKind() != CCAttrKind) {
+ S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << FunctionType::getNameForCallConv(CC)
+ << FunctionType::getNameForCallConv(CCOld);
+ attr.setInvalid();
+ return true;
+ }
}
- // Diagnose the use of X86 fastcall on varargs or unprototyped functions.
- if (CC == CC_X86FastCall) {
- if (isa<FunctionNoProtoType>(fn)) {
- S.Diag(attr.getLoc(), diag::err_cconv_knr)
- << FunctionType::getNameForCallConv(CC);
+ // Diagnose use of callee-cleanup calling convention on variadic functions.
+ if (isCalleeCleanup(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)
+ DiagID = diag::warn_cconv_varargs;
+
+ S.Diag(attr.getLoc(), DiagID) << FunctionType::getNameForCallConv(CC);
attr.setInvalid();
return true;
}
+ }
- const FunctionProtoType *FnP = cast<FunctionProtoType>(fn);
- if (FnP->isVariadic()) {
- S.Diag(attr.getLoc(), diag::err_cconv_varargs)
+ // Diagnose the use of X86 fastcall on unprototyped functions.
+ if (CC == CC_X86FastCall) {
+ if (isa<FunctionNoProtoType>(fn)) {
+ S.Diag(attr.getLoc(), diag::err_cconv_knr)
<< FunctionType::getNameForCallConv(CC);
attr.setInvalid();
return true;
@@ -4291,27 +4576,66 @@ 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);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ QualType Equivalent =
+ unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ type = S.Context.getAttributedType(CCAttrKind, type, Equivalent);
return true;
}
+void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) {
+ const FunctionType *FT = T->castAs<FunctionType>();
+ bool IsVariadic = (isa<FunctionProtoType>(FT) &&
+ cast<FunctionProtoType>(FT)->isVariadic());
+ CallingConv CC = FT->getCallConv();
+
+ // Only adjust types with the default convention. For example, on Windows we
+ // should adjust a __cdecl type to __thiscall for instance methods, and a
+ // __thiscall type to __cdecl for static methods.
+ CallingConv DefaultCC =
+ Context.getDefaultCallingConvention(IsVariadic, IsStatic);
+ if (CC != DefaultCC)
+ return;
+
+ // Check if there was an explicit attribute, but only look through parens.
+ // The intent is to look for an attribute on the current declarator, but not
+ // one that came from a typedef.
+ QualType R = T.IgnoreParens();
+ while (const AttributedType *AT = dyn_cast<AttributedType>(R)) {
+ if (AT->isCallingConv())
+ return;
+ R = AT->getModifiedType().IgnoreParens();
+ }
+
+ // FIXME: This loses sugar. This should probably be fixed with an implicit
+ // AttributedType node that adjusts the convention.
+ CC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
+ FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(CC));
+ FunctionTypeUnwrapper Unwrapped(*this, T);
+ T = Unwrapped.wrap(*this, FT);
+}
+
/// Handle OpenCL image access qualifiers: read_only, write_only, read_write
static void HandleOpenCLImageAccessAttribute(QualType& CurType,
const AttributeList &Attr,
Sema &S) {
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
Attr.setInvalid();
return;
}
- Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
+ Expr *sizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
llvm::APSInt arg(32);
if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
!sizeExpr->isIntegerConstantExpr(arg, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "opencl_image_access" << sizeExpr->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << sizeExpr->getSourceRange();
Attr.setInvalid();
return;
}
@@ -4342,21 +4666,25 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
Sema &S) {
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
Attr.setInvalid();
return;
}
- Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
+ Expr *sizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
llvm::APSInt vecSize(32);
if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "vector_size" << sizeExpr->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << sizeExpr->getSourceRange();
Attr.setInvalid();
return;
}
- // the base type must be integer or float, and can't already be a vector.
- if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) {
+ // The base type must be integer (not Boolean or enumeration) or float, and
+ // can't already be a vector.
+ if (!CurType->isBuiltinType() || CurType->isBooleanType() ||
+ (!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
Attr.setInvalid();
return;
@@ -4372,6 +4700,12 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
Attr.setInvalid();
return;
}
+ if (VectorType::isVectorSizeTooLarge(vectorSize / typeSize)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_size_too_large)
+ << sizeExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
if (vectorSize == 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
<< sizeExpr->getSourceRange();
@@ -4390,14 +4724,21 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
static void HandleExtVectorTypeAttr(QualType &CurType,
const AttributeList &Attr,
Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
+ return;
+ }
+
Expr *sizeExpr;
// Special case where the argument is a template id.
- if (Attr.getParameterName()) {
+ if (Attr.isArgIdent(0)) {
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
UnqualifiedId id;
- id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
+ id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
id, false, false);
@@ -4406,12 +4747,7 @@ static void HandleExtVectorTypeAttr(QualType &CurType,
sizeExpr = Size.get();
} else {
- // check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- return;
- }
- sizeExpr = Attr.getArg(0);
+ sizeExpr = Attr.getArgAsExpr(0);
}
// Create the vector type.
@@ -4420,6 +4756,43 @@ static void HandleExtVectorTypeAttr(QualType &CurType,
CurType = T;
}
+static bool isPermittedNeonBaseType(QualType &Ty,
+ VectorType::VectorKind VecKind,
+ bool IsAArch64) {
+ const BuiltinType *BTy = Ty->getAs<BuiltinType>();
+ if (!BTy)
+ return false;
+
+ if (VecKind == VectorType::NeonPolyVector) {
+ if (IsAArch64) {
+ // AArch64 polynomial vectors are unsigned and support poly64.
+ return BTy->getKind() == BuiltinType::UChar ||
+ BTy->getKind() == BuiltinType::UShort ||
+ BTy->getKind() == BuiltinType::ULongLong;
+ } else {
+ // AArch32 polynomial vector are signed.
+ return BTy->getKind() == BuiltinType::SChar ||
+ BTy->getKind() == BuiltinType::Short;
+ }
+ }
+
+ // Non-polynomial vector types: the usual suspects are allowed, as well as
+ // float64_t on AArch64.
+ if (IsAArch64 && BTy->getKind() == BuiltinType::Double)
+ return true;
+
+ return BTy->getKind() == BuiltinType::SChar ||
+ BTy->getKind() == BuiltinType::UChar ||
+ BTy->getKind() == BuiltinType::Short ||
+ BTy->getKind() == BuiltinType::UShort ||
+ BTy->getKind() == BuiltinType::Int ||
+ BTy->getKind() == BuiltinType::UInt ||
+ BTy->getKind() == BuiltinType::LongLong ||
+ BTy->getKind() == BuiltinType::ULongLong ||
+ BTy->getKind() == BuiltinType::Float ||
+ BTy->getKind() == BuiltinType::Half;
+}
+
/// HandleNeonVectorTypeAttr - The "neon_vector_type" and
/// "neon_polyvector_type" attributes are used to create vector types that
/// are mangled according to ARM's ABI. Otherwise, these types are identical
@@ -4429,43 +4802,41 @@ static void HandleExtVectorTypeAttr(QualType &CurType,
/// match one of the standard Neon vector types.
static void HandleNeonVectorTypeAttr(QualType& CurType,
const AttributeList &Attr, Sema &S,
- VectorType::VectorKind VecKind,
- const char *AttrName) {
+ VectorType::VectorKind VecKind) {
+ // Target must have NEON
+ if (!S.Context.getTargetInfo().hasFeature("neon")) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr.getName();
+ Attr.setInvalid();
+ return;
+ }
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr.getName() << 1;
Attr.setInvalid();
return;
}
// The number of elements must be an ICE.
- Expr *numEltsExpr = static_cast<Expr *>(Attr.getArg(0));
+ Expr *numEltsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
llvm::APSInt numEltsInt(32);
if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() ||
!numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << AttrName << numEltsExpr->getSourceRange();
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr.getName() << AANT_ArgumentIntegerConstant
+ << numEltsExpr->getSourceRange();
Attr.setInvalid();
return;
}
// Only certain element types are supported for Neon vectors.
- const BuiltinType* BTy = CurType->getAs<BuiltinType>();
- if (!BTy ||
- (VecKind == VectorType::NeonPolyVector &&
- BTy->getKind() != BuiltinType::SChar &&
- BTy->getKind() != BuiltinType::Short) ||
- (BTy->getKind() != BuiltinType::SChar &&
- BTy->getKind() != BuiltinType::UChar &&
- BTy->getKind() != BuiltinType::Short &&
- BTy->getKind() != BuiltinType::UShort &&
- BTy->getKind() != BuiltinType::Int &&
- BTy->getKind() != BuiltinType::UInt &&
- BTy->getKind() != BuiltinType::LongLong &&
- BTy->getKind() != BuiltinType::ULongLong &&
- BTy->getKind() != BuiltinType::Float)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) <<CurType;
+ llvm::Triple::ArchType Arch =
+ S.Context.getTargetInfo().getTriple().getArch();
+ if (!isPermittedNeonBaseType(CurType, VecKind,
+ Arch == llvm::Triple::aarch64)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
Attr.setInvalid();
return;
}
+
// The total size of the vector must be 64 or 128 bits.
unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
unsigned numElts = static_cast<unsigned>(numEltsInt.getZExtValue());
@@ -4559,13 +4930,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
break;
case AttributeList::AT_NeonVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
- VectorType::NeonVector, "neon_vector_type");
+ VectorType::NeonVector);
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_NeonPolyVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
- VectorType::NeonPolyVector,
- "neon_polyvector_type");
+ VectorType::NeonPolyVector);
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_OpenCLImageAccess:
@@ -4574,12 +4944,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
break;
case AttributeList::AT_Win64:
- case AttributeList::AT_Ptr32:
- case AttributeList::AT_Ptr64:
- // FIXME: Don't ignore these. We have partial handling for them as
- // declaration attributes in SemaDeclAttr.cpp; that should be moved here.
attr.setUsedAsTypeAttr();
break;
+ MS_TYPE_ATTRS_CASELIST:
+ if (!handleMSPointerTypeQualifierAttr(state, attr, type))
+ attr.setUsedAsTypeAttr();
+ break;
case AttributeList::AT_NSReturnsRetained:
if (!state.getSema().getLangOpts().ObjCAutoRefCount)
@@ -4621,41 +4991,46 @@ bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser){
// Fast path the case where the type is already complete.
if (!T->isIncompleteType())
+ // FIXME: The definition might not be visible.
return false;
// Incomplete array types may be completed by the initializer attached to
- // their definitions. For static data members of class templates we need to
- // instantiate the definition to get this initializer and complete the type.
+ // their definitions. For static data members of class templates and for
+ // variable templates, we need to instantiate the definition to get this
+ // initializer and complete the type.
if (T->isIncompleteArrayType()) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (Var->isStaticDataMember() &&
- Var->getInstantiatedFromStaticDataMember()) {
+ if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
+ SourceLocation PointOfInstantiation = E->getExprLoc();
- MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
- assert(MSInfo && "Missing member specialization information?");
- if (MSInfo->getTemplateSpecializationKind()
- != TSK_ExplicitSpecialization) {
+ if (MemberSpecializationInfo *MSInfo =
+ Var->getMemberSpecializationInfo()) {
// If we don't already have a point of instantiation, this is it.
if (MSInfo->getPointOfInstantiation().isInvalid()) {
- MSInfo->setPointOfInstantiation(E->getLocStart());
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
// This is a modification of an existing AST node. Notify
// listeners.
if (ASTMutationListener *L = getASTMutationListener())
L->StaticDataMemberInstantiated(Var);
}
+ } else {
+ VarTemplateSpecializationDecl *VarSpec =
+ cast<VarTemplateSpecializationDecl>(Var);
+ if (VarSpec->getPointOfInstantiation().isInvalid())
+ VarSpec->setPointOfInstantiation(PointOfInstantiation);
+ }
- InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var);
+ InstantiateVariableDefinition(PointOfInstantiation, Var);
- // Update the type to the newly instantiated definition's type both
- // here and within the expression.
- if (VarDecl *Def = Var->getDefinition()) {
- DRE->setDecl(Def);
- T = Def->getType();
- DRE->setType(T);
- E->setType(T);
- }
+ // Update the type to the newly instantiated definition's type both
+ // here and within the expression.
+ if (VarDecl *Def = Var->getDefinition()) {
+ DRE->setDecl(Def);
+ T = Def->getType();
+ DRE->setType(T);
+ E->setType(T);
}
// We still go on to try to complete the type independently, as it
@@ -4714,6 +5089,20 @@ bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
/// @c false otherwise.
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser) {
+ if (RequireCompleteTypeImpl(Loc, T, Diagnoser))
+ return true;
+ if (const TagType *Tag = T->getAs<TagType>()) {
+ if (!Tag->getDecl()->isCompleteDefinitionRequired()) {
+ Tag->getDecl()->setCompleteDefinitionRequired();
+ Consumer.HandleTagDeclRequiredDefinition(Tag->getDecl());
+ }
+ }
+ return false;
+}
+
+/// \brief The implementation of RequireCompleteType
+bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
+ TypeDiagnoser &Diagnoser) {
// FIXME: Add this assertion to make sure we always get instantiation points.
// assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");
// FIXME: Add this assertion to help us flush out problems with
@@ -4726,7 +5115,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
NamedDecl *Def = 0;
if (!T->isIncompleteType(&Def)) {
// If we know about the definition but it is not visible, complain.
- if (!Diagnoser.Suppressed && Def && !LookupResult::isVisible(Def)) {
+ if (!Diagnoser.Suppressed && Def && !LookupResult::isVisible(*this, Def)) {
// Suppress this error outside of a SFINAE context if we've already
// emitted the error once for this type. There's no usefulness in
// repeating the diagnostic.
@@ -4746,6 +5135,14 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
return false;
}
+ // FIXME: If there's an unimported definition of this type in a module (for
+ // instance, because we forward declared it, then imported the definition),
+ // import that definition now.
+ // FIXME: What about other cases where an import extends a redeclaration
+ // chain for a declaration that can be accessed through a mechanism other
+ // than name lookup (eg, referenced in a template, or a variable whose type
+ // could be completed by the module)?
+
const TagType *Tag = T->getAs<TagType>();
const ObjCInterfaceType *IFace = 0;
@@ -4808,6 +5205,12 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
return true;
// 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);
+ return true;
+ }
+
Diagnoser.diagnose(*this, Loc, T);
// If the type was a forward declaration of a class/struct/union
@@ -4822,6 +5225,11 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
if (IFace && !IFace->getDecl()->isInvalidDecl())
Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
+ // If we have external information that we can use to suggest a fix,
+ // produce a note.
+ if (ExternalSource)
+ ExternalSource->MaybeDiagnoseMissingCompleteType(Loc, T);
+
return true;
}
OpenPOWER on IntegriCloud