diff options
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r-- | lib/Sema/SemaType.cpp | 810 |
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; } |