diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2012-08-15 20:02:54 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2012-08-15 20:02:54 +0000 |
commit | 56d91b49b13fe55c918afbda19f6165b5fbff87a (patch) | |
tree | 9abb1a658a297776086f4e0dfa6ca533de02104e /lib/Sema/SemaType.cpp | |
parent | 41e20f564abdb05101d6b2b29c59459a966c22cc (diff) |
Notes
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r-- | lib/Sema/SemaType.cpp | 568 |
1 files changed, 351 insertions, 217 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 1400e7e5c419..20fe036348ba 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -35,19 +35,19 @@ using namespace clang; /// isOmittedBlockReturnType - Return true if this declarator is missing a -/// return type because this is a omitted return type on a block literal. +/// return type because this is a omitted return type on a block literal. static bool isOmittedBlockReturnType(const Declarator &D) { if (D.getContext() != Declarator::BlockLiteralContext || D.getDeclSpec().hasTypeSpecifier()) return false; - + if (D.getNumTypeObjects() == 0) return true; // ^{ ... } - + if (D.getNumTypeObjects() == 1 && D.getTypeObject(0).Kind == DeclaratorChunk::Function) return true; // ^(int X, float Y) { ... } - + return false; } @@ -59,12 +59,12 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, unsigned diagID = 0; switch (attr.getKind()) { - case AttributeList::AT_objc_gc: + case AttributeList::AT_ObjCGC: diagID = diag::warn_pointer_attribute_wrong_type; useExpansionLoc = true; break; - case AttributeList::AT_objc_ownership: + case AttributeList::AT_ObjCOwnership: diagID = diag::warn_objc_object_attribute_wrong_type; useExpansionLoc = true; break; @@ -93,19 +93,19 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, // objc_gc applies to Objective-C pointers or, otherwise, to the // smallest available pointer type (i.e. 'void*' in 'void**'). #define OBJC_POINTER_TYPE_ATTRS_CASELIST \ - case AttributeList::AT_objc_gc: \ - case AttributeList::AT_objc_ownership + case AttributeList::AT_ObjCGC: \ + case AttributeList::AT_ObjCOwnership // Function type attributes. #define FUNCTION_TYPE_ATTRS_CASELIST \ - case AttributeList::AT_noreturn: \ - case AttributeList::AT_cdecl: \ - case AttributeList::AT_fastcall: \ - case AttributeList::AT_stdcall: \ - case AttributeList::AT_thiscall: \ - case AttributeList::AT_pascal: \ - case AttributeList::AT_regparm: \ - case AttributeList::AT_pcs \ + case AttributeList::AT_NoReturn: \ + case AttributeList::AT_CDecl: \ + case AttributeList::AT_FastCall: \ + case AttributeList::AT_StdCall: \ + case AttributeList::AT_ThisCall: \ + case AttributeList::AT_Pascal: \ + case AttributeList::AT_Regparm: \ + case AttributeList::AT_Pcs \ namespace { /// An object which stores processing state for the entire @@ -284,9 +284,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, static bool handleObjCPointerTypeAttr(TypeProcessingState &state, AttributeList &attr, QualType &type) { - if (attr.getKind() == AttributeList::AT_objc_gc) + if (attr.getKind() == AttributeList::AT_ObjCGC) return handleObjCGCTypeAttr(state, attr, type); - assert(attr.getKind() == AttributeList::AT_objc_ownership); + assert(attr.getKind() == AttributeList::AT_ObjCOwnership); return handleObjCOwnershipTypeAttr(state, attr, type); } @@ -412,7 +412,7 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state, continue; } } - + diagnoseBadTypeAttribute(state.getSema(), attr, type); } @@ -505,7 +505,7 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType); break; - case AttributeList::AT_ns_returns_retained: + case AttributeList::AT_NSReturnsRetained: if (!state.getSema().getLangOpts().ObjCAutoRefCount) break; // fallthrough @@ -554,7 +554,8 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, // ...and *prepend* it to the declarator. declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction( /*proto*/ true, - /*variadic*/ false, SourceLocation(), + /*variadic*/ false, + /*ambiguous*/ false, SourceLocation(), /*args*/ 0, 0, /*type quals*/ 0, /*ref-qualifier*/true, SourceLocation(), @@ -573,7 +574,8 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, /// \brief Convert the specified declspec to the appropriate type /// object. -/// \param D the declarator containing the declaration specifier. +/// \param state Specifies the declarator containing the declaration specifier +/// to be converted, along with other associated processing state. /// \returns The type described by the declaration specifiers. This function /// never returns null. static QualType ConvertDeclSpecToType(TypeProcessingState &state) { @@ -586,7 +588,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { SourceLocation DeclLoc = declarator.getIdentifierLoc(); if (DeclLoc.isInvalid()) DeclLoc = DS.getLocStart(); - + ASTContext &Context = S.Context; QualType Result; @@ -639,7 +641,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { Result = Context.getObjCObjectPointerType(Result); break; } - + // If this is a missing declspec in a block literal return context, then it // is inferred from the return statements inside the block. // The declspec is always missing in a lambda expr context; it is either @@ -695,7 +697,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { case DeclSpec::TSW_long: Result = Context.LongTy; break; case DeclSpec::TSW_longlong: Result = Context.LongLongTy; - + // long long is a C99 feature. if (!S.getLangOpts().C99) S.Diag(DS.getTypeSpecWidthLoc(), @@ -710,7 +712,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { case DeclSpec::TSW_long: Result = Context.UnsignedLongTy; break; case DeclSpec::TSW_longlong: Result = Context.UnsignedLongLongTy; - + // long long is a C99 feature. if (!S.getLangOpts().C99) S.Diag(DS.getTypeSpecWidthLoc(), @@ -762,10 +764,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // If the type is deprecated or unavailable, diagnose it. S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc()); - + assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 && DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!"); - + // TypeQuals handled by caller. Result = Context.getTypeDeclType(D); @@ -858,7 +860,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { Result = Context.IntTy; declarator.setInvalidType(true); } - break; + break; case DeclSpec::TST_auto: { // TypeQuals handled by caller. @@ -878,7 +880,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { Result = Context.IntTy; declarator.setInvalidType(true); } - break; + break; case DeclSpec::TST_error: Result = Context.IntTy; @@ -983,15 +985,15 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // C90 6.5.3 constraints: "The same type qualifier shall not appear more // than once in the same specifier-list or qualifier-list, either directly // or via one or more typedefs." - if (!S.getLangOpts().C99 && !S.getLangOpts().CPlusPlus + if (!S.getLangOpts().C99 && !S.getLangOpts().CPlusPlus && TypeQuals & Result.getCVRQualifiers()) { if (TypeQuals & DeclSpec::TQ_const && Result.isConstQualified()) { - S.Diag(DS.getConstSpecLoc(), diag::ext_duplicate_declspec) + S.Diag(DS.getConstSpecLoc(), diag::ext_duplicate_declspec) << "const"; } if (TypeQuals & DeclSpec::TQ_volatile && Result.isVolatileQualified()) { - S.Diag(DS.getVolatileSpecLoc(), diag::ext_duplicate_declspec) + S.Diag(DS.getVolatileSpecLoc(), diag::ext_duplicate_declspec) << "volatile"; } @@ -1036,7 +1038,7 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, if (!PTy->getPointeeType()->isIncompleteOrObjectType()) { DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; ProblemTy = T->getAs<PointerType>()->getPointeeType(); - } + } } else if (!Ty->isDependentType()) { // FIXME: this deserves a proper diagnostic DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; @@ -1083,7 +1085,7 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type, // If we are in an unevaluated context, like sizeof, skip adding a // qualification. - } else if (S.ExprEvalContexts.back().Context == Sema::Unevaluated) { + } else if (S.isUnevaluatedContext()) { return type; // If that failed, give an error and recover using __strong. __strong @@ -1157,14 +1159,14 @@ QualType Sema::BuildPointerType(QualType T, QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, SourceLocation Loc, DeclarationName Entity) { - assert(Context.getCanonicalType(T) != Context.OverloadTy && + assert(Context.getCanonicalType(T) != Context.OverloadTy && "Unresolved overloaded function type"); - + // C++0x [dcl.ref]p6: - // If a typedef (7.1.3), a type template-parameter (14.3.1), or a - // decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a - // type T, an attempt to create the type "lvalue reference to cv TR" creates - // the type "lvalue reference to T", while an attempt to create the type + // If a typedef (7.1.3), a type template-parameter (14.3.1), or a + // decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a + // type T, an attempt to create the type "lvalue reference to cv TR" creates + // the type "lvalue reference to T", while an attempt to create the type // "rvalue reference to cv TR" creates the type TR. bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>(); @@ -1205,9 +1207,20 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) { // If the size is an ICE, it certainly isn't a VLA. If we're in a GNU mode // (like gnu99, but not c99) accept any evaluatable value as an extension. - return S.VerifyIntegerConstantExpression( - ArraySize, &SizeVal, S.PDiag(), S.LangOpts.GNUMode, - S.PDiag(diag::ext_vla_folded_to_constant)).isInvalid(); + class VLADiagnoser : public Sema::VerifyICEDiagnoser { + public: + VLADiagnoser() : Sema::VerifyICEDiagnoser(true) {} + + virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) { + } + + virtual void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR) { + S.Diag(Loc, diag::ext_vla_folded_to_constant) << SR; + } + } Diagnoser; + + return S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser, + S.LangOpts.GNUMode).isInvalid(); } @@ -1219,9 +1232,7 @@ static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) { /// /// \param ArraySize Expression describing the size of the array. /// -/// \param Loc The location of the entity whose type involves this -/// array type or, if there is no such entity, the location of the -/// type that will have array type. +/// \param Brackets The range from the opening '[' to the closing ']'. /// /// \param Entity The name of the entity that involves the array /// type, if known. @@ -1236,25 +1247,30 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, if (getLangOpts().CPlusPlus) { // C++ [dcl.array]p1: // T is called the array element type; this type shall not be a reference - // type, the (possibly cv-qualified) type void, a function type or an + // type, the (possibly cv-qualified) type void, a function type or an // abstract class type. // + // C++ [dcl.array]p3: + // When several "array of" specifications are adjacent, [...] only the + // first of the constant expressions that specify the bounds of the arrays + // may be omitted. + // // Note: function types are handled in the common path with C. if (T->isReferenceType()) { Diag(Loc, diag::err_illegal_decl_array_of_references) << getPrintableNameForEntity(Entity) << T; return QualType(); } - - if (T->isVoidType()) { + + if (T->isVoidType() || T->isIncompleteArrayType()) { Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T; return QualType(); } - - if (RequireNonAbstractType(Brackets.getBegin(), T, + + if (RequireNonAbstractType(Brackets.getBegin(), T, diag::err_array_of_abstract_type)) return QualType(); - + } else { // C99 6.7.5.2p1: If the element type is an incomplete or function type, // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]()) @@ -1350,7 +1366,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, if (ConstVal == 0) { // GCC accepts zero sized static arrays. We allow them when // we're not in a SFINAE context. - Diag(ArraySize->getLocStart(), + Diag(ArraySize->getLocStart(), isSFINAEContext()? diag::err_typecheck_zero_array_size : diag::ext_typecheck_zero_array_size) << ArraySize->getSourceRange(); @@ -1361,9 +1377,9 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, << ArraySize->getSourceRange(); ASM = ArrayType::Normal; } - } else if (!T->isDependentType() && !T->isVariablyModifiedType() && + } else if (!T->isDependentType() && !T->isVariablyModifiedType() && !T->isIncompleteType()) { - // Is the array too large? + // Is the array too large? unsigned ActiveSizeBits = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal); if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) @@ -1371,7 +1387,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, << ConstVal.toString(10) << ArraySize->getSourceRange(); } - + T = Context.getConstantArrayType(T, ConstVal, ASM, Quals); } // If this is not C99, extwarn about VLA's and C99 array size modifiers. @@ -1379,13 +1395,13 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, if (T->isVariableArrayType()) { // Prohibit the use of non-POD types in VLAs. QualType BaseT = Context.getBaseElementType(T); - if (!T->isDependentType() && + if (!T->isDependentType() && !BaseT.isPODType(Context) && !BaseT->isObjCLifetimeType()) { Diag(Loc, diag::err_vla_non_pod) << BaseT; return QualType(); - } + } // Prohibit the use of VLAs during template argument deduction. else if (isSFINAEContext()) { Diag(Loc, diag::err_vla_in_sfinae); @@ -1480,7 +1496,7 @@ QualType Sema::BuildFunctionType(QualType T, SourceLocation Loc, DeclarationName Entity, FunctionType::ExtInfo Info) { if (T->isArrayType() || T->isFunctionType()) { - Diag(Loc, diag::err_func_returning_array_function) + Diag(Loc, diag::err_func_returning_array_function) << T->isFunctionType() << T; return QualType(); } @@ -1581,18 +1597,14 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, /// /// \param T The type to which we'll be building a block pointer. /// -/// \param CVR The cvr-qualifiers to be applied to the block pointer type. -/// -/// \param Loc The location of the entity whose type involves this -/// block pointer type or, if there is no such entity, the location of the -/// type that will have block pointer type. +/// \param Loc The source location, used for diagnostics. /// /// \param Entity The name of the entity that involves the block pointer /// type, if known. /// /// \returns A suitable block pointer type, if there are no /// errors. Otherwise, returns a NULL type. -QualType Sema::BuildBlockPointerType(QualType T, +QualType Sema::BuildBlockPointerType(QualType T, SourceLocation Loc, DeclarationName Entity) { if (!T->isFunctionType()) { @@ -1688,7 +1700,7 @@ static void inferARCWriteback(TypeProcessingState &state, // Otherwise, modify the type in-place. Qualifiers qs; - + if (declSpecType->isObjCARCImplicitlyUnretainedType()) qs.addObjCLifetime(Qualifiers::OCL_ExplicitNone); else @@ -1711,7 +1723,7 @@ static void inferARCWriteback(TypeProcessingState &state, return; for (const AttributeList *attr = chunk.getAttrs(); attr; attr = attr->getNext()) - if (attr->getKind() == AttributeList::AT_objc_ownership) + if (attr->getKind() == AttributeList::AT_ObjCOwnership) return; transferARCOwnershipToDeclaratorChunk(state, Qualifiers::OCL_Autoreleasing, @@ -1786,7 +1798,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case UnqualifiedId::IK_LiteralOperatorId: case UnqualifiedId::IK_TemplateId: T = ConvertDeclSpecToType(state); - + if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) { OwnedTagDecl = cast<TagDecl>(D.getDeclSpec().getRepAsDecl()); // Owned declaration is embedded in declarator. @@ -1798,14 +1810,16 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case UnqualifiedId::IK_ConstructorTemplateId: case UnqualifiedId::IK_DestructorName: // Constructors and destructors don't have return types. Use - // "void" instead. + // "void" instead. T = SemaRef.Context.VoidTy; + if (AttributeList *attrs = D.getDeclSpec().getAttributes().getList()) + processTypeAttrs(state, T, true, attrs); break; case UnqualifiedId::IK_ConversionFunctionId: // The result type of a conversion function is the type that it // converts to. - T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId, + T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId, &ReturnTypeInfo); break; } @@ -1890,7 +1904,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex); if (DeclType.Kind == DeclaratorChunk::Function) { const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; - if (FTI.TrailingReturnType) { + if (FTI.hasTrailingReturnType()) { Error = -1; break; } @@ -2029,6 +2043,102 @@ static void checkQualifiedFunction(Sema &S, QualType T, << getFunctionQualifiersAsString(T->castAs<FunctionProtoType>()); } +/// Produce an approprioate diagnostic for an ambiguity between a function +/// declarator and a C++ direct-initializer. +static void warnAboutAmbiguousFunction(Sema &S, Declarator &D, + DeclaratorChunk &DeclType, QualType RT) { + const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; + assert(FTI.isAmbiguous && "no direct-initializer / function ambiguity"); + + // If the return type is void there is no ambiguity. + if (RT->isVoidType()) + return; + + // An initializer for a non-class type can have at most one argument. + if (!RT->isRecordType() && FTI.NumArgs > 1) + return; + + // An initializer for a reference must have exactly one argument. + if (RT->isReferenceType() && FTI.NumArgs != 1) + return; + + // Only warn if this declarator is declaring a function at block scope, and + // doesn't have a storage class (such as 'extern') specified. + if (!D.isFunctionDeclarator() || + D.getFunctionDefinitionKind() != FDK_Declaration || + !S.CurContext->isFunctionOrMethod() || + D.getDeclSpec().getStorageClassSpecAsWritten() + != DeclSpec::SCS_unspecified) + return; + + // Inside a condition, a direct initializer is not permitted. We allow one to + // be parsed in order to give better diagnostics in condition parsing. + if (D.getContext() == Declarator::ConditionContext) + return; + + SourceRange ParenRange(DeclType.Loc, DeclType.EndLoc); + + S.Diag(DeclType.Loc, + FTI.NumArgs ? diag::warn_parens_disambiguated_as_function_declaration + : diag::warn_empty_parens_are_function_decl) + << ParenRange; + + // If the declaration looks like: + // T var1, + // f(); + // and name lookup finds a function named 'f', then the ',' was + // probably intended to be a ';'. + if (!D.isFirstDeclarator() && D.getIdentifier()) { + FullSourceLoc Comma(D.getCommaLoc(), S.SourceMgr); + FullSourceLoc Name(D.getIdentifierLoc(), S.SourceMgr); + if (Comma.getFileID() != Name.getFileID() || + Comma.getSpellingLineNumber() != Name.getSpellingLineNumber()) { + LookupResult Result(S, D.getIdentifier(), SourceLocation(), + Sema::LookupOrdinaryName); + if (S.LookupName(Result, S.getCurScope())) + S.Diag(D.getCommaLoc(), diag::note_empty_parens_function_call) + << FixItHint::CreateReplacement(D.getCommaLoc(), ";") + << D.getIdentifier(); + } + } + + if (FTI.NumArgs > 0) { + // For a declaration with parameters, eg. "T var(T());", suggest adding parens + // around the first parameter to turn the declaration into a variable + // declaration. + SourceRange Range = FTI.ArgInfo[0].Param->getSourceRange(); + SourceLocation B = Range.getBegin(); + SourceLocation E = S.PP.getLocForEndOfToken(Range.getEnd()); + // FIXME: Maybe we should suggest adding braces instead of parens + // in C++11 for classes that don't have an initializer_list constructor. + S.Diag(B, diag::note_additional_parens_for_variable_declaration) + << FixItHint::CreateInsertion(B, "(") + << FixItHint::CreateInsertion(E, ")"); + } else { + // For a declaration without parameters, eg. "T var();", suggest replacing the + // parens with an initializer to turn the declaration into a variable + // declaration. + const CXXRecordDecl *RD = RT->getAsCXXRecordDecl(); + + // Empty parens mean value-initialization, and no parens mean + // default initialization. These are equivalent if the default + // constructor is user-provided or if zero-initialization is a + // no-op. + if (RD && RD->hasDefinition() && + (RD->isEmpty() || RD->hasUserProvidedDefaultConstructor())) + S.Diag(DeclType.Loc, diag::note_empty_parens_default_ctor) + << FixItHint::CreateRemoval(ParenRange); + else { + std::string Init = S.getFixItZeroInitializerForType(RT); + if (Init.empty() && S.LangOpts.CPlusPlus0x) + Init = "{}"; + if (!Init.empty()) + S.Diag(DeclType.Loc, diag::note_empty_parens_zero_initialize) + << FixItHint::CreateReplacement(ParenRange, Init); + } + } +} + static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, QualType declSpecType, TypeSourceInfo *TInfo) { @@ -2165,12 +2275,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // trailing-return-type is only required if we're declaring a function, // and not, for instance, a pointer to a function. if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto && - !FTI.TrailingReturnType && chunkIndex == 0) { + !FTI.hasTrailingReturnType() && chunkIndex == 0) { S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_auto_missing_trailing_return); T = Context.IntTy; D.setInvalidType(true); - } else if (FTI.TrailingReturnType) { + } else if (FTI.hasTrailingReturnType()) { // T must be exactly 'auto' at this point. See CWG issue 681. if (isa<ParenType>(T)) { S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), @@ -2184,10 +2294,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, << T << D.getDeclSpec().getSourceRange(); D.setInvalidType(true); } - - T = S.GetTypeFromParser( - ParsedType::getFromOpaquePtr(FTI.TrailingReturnType), - &TInfo); + T = S.GetTypeFromParser(FTI.getTrailingReturnType(), &TInfo); + if (T.isNull()) { + // An error occurred parsing the trailing return type. + T = Context.IntTy; + D.setInvalidType(true); + } } } @@ -2259,6 +2371,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, << (D.getContext() == Declarator::AliasDeclContext || D.getContext() == Declarator::AliasTemplateContext); + // If we see "T var();" or "T var(T());" at block scope, it is probably + // an attempt to initialize a variable, not a function declaration. + if (FTI.isAmbiguous) + warnAboutAmbiguousFunction(S, D, DeclType, T); + if (!FTI.NumArgs && !FTI.isVariadic && !LangOpts.CPlusPlus) { // Simple void foo(), where the incoming T is the result type. T = Context.getFunctionNoProtoType(T); @@ -2270,7 +2387,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, bool Overloadable = false; for (const AttributeList *Attrs = D.getAttributes(); Attrs; Attrs = Attrs->getNext()) { - if (Attrs->getKind() == AttributeList::AT_overloadable) { + if (Attrs->getKind() == AttributeList::AT_Overloadable) { Overloadable = true; break; } @@ -2290,12 +2407,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, FunctionProtoType::ExtProtoInfo EPI; EPI.Variadic = FTI.isVariadic; - EPI.HasTrailingReturn = FTI.TrailingReturnType; + EPI.HasTrailingReturn = FTI.hasTrailingReturnType(); EPI.TypeQuals = FTI.TypeQuals; EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None : FTI.RefQualifierIsLValueRef? RQ_LValue : RQ_RValue; - + // Otherwise, we have a function with an argument list that is // potentially variadic. SmallVector<QualType, 16> ArgTys; @@ -2311,7 +2428,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, assert(!ArgTy.isNull() && "Couldn't parse type?"); // Adjust the parameter type. - assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) && + assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) && "Unadjusted type?"); // Look for 'void'. void is allowed only as a single argument to a @@ -2374,7 +2491,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, SmallVector<ParsedType, 2> DynamicExceptions; SmallVector<SourceRange, 2> DynamicExceptionRanges; Expr *NoexceptExpr = 0; - + if (FTI.getExceptionSpecType() == EST_Dynamic) { // FIXME: It's rather inefficient to have to split into two vectors // here. @@ -2388,14 +2505,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) { NoexceptExpr = FTI.NoexceptExpr; } - + S.checkExceptionSpecification(FTI.getExceptionSpecType(), DynamicExceptions, DynamicExceptionRanges, NoexceptExpr, Exceptions, EPI); - + if (FTI.getExceptionSpecType() == EST_None && ImplicitlyNoexcept && chunkIndex == 0) { // Only the outermost chunk is marked noexcept, of course. @@ -2475,7 +2592,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>(); assert(FnTy && "Why oh why is there not a FunctionProtoType here?"); - // C++ 8.3.5p4: + // C++ 8.3.5p4: // A cv-qualifier-seq shall only be part of the function type // for a nonstatic member function, the function type to which a pointer // to member refers, or the top-level function type of a function typedef @@ -2503,7 +2620,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Rebuild function type adding a 'const' qualifier. FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo(); EPI.TypeQuals |= DeclSpec::TQ_const; - T = Context.getFunctionType(FnTy->getResultType(), + T = Context.getFunctionType(FnTy->getResultType(), FnTy->arg_type_begin(), FnTy->getNumArgs(), EPI); } @@ -2540,7 +2657,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc()); if (!RemovalLocs.empty()) { std::sort(RemovalLocs.begin(), RemovalLocs.end(), - SourceManager::LocBeforeThanCompare(S.getSourceManager())); + BeforeThanCompare<SourceLocation>(S.getSourceManager())); RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back()); Loc = RemovalLocs.front(); } @@ -2556,7 +2673,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, EPI.TypeQuals = 0; EPI.RefQualifier = RQ_None; - T = Context.getFunctionType(FnTy->getResultType(), + T = Context.getFunctionType(FnTy->getResultType(), FnTy->arg_type_begin(), FnTy->getNumArgs(), EPI); } @@ -2572,31 +2689,31 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // C++0x [dcl.constexpr]p9: // A constexpr specifier used in an object declaration declares the object - // as const. + // as const. if (D.getDeclSpec().isConstexprSpecified() && T->isObjectType()) { T.addConst(); } - // If there was an ellipsis in the declarator, the declaration declares a + // If there was an ellipsis in the declarator, the declaration declares a // parameter pack whose type may be a pack expansion type. if (D.hasEllipsis() && !T.isNull()) { // C++0x [dcl.fct]p13: - // A declarator-id or abstract-declarator containing an ellipsis shall + // A declarator-id or abstract-declarator containing an ellipsis shall // only be used in a parameter-declaration. Such a parameter-declaration // is a parameter pack (14.5.3). [...] switch (D.getContext()) { case Declarator::PrototypeContext: // 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 + // [...] When it is part of a parameter-declaration-clause, the + // parameter pack is a function parameter pack (14.5.3). The type T // of the declarator-id of the function parameter pack shall contain - // a template parameter pack; each template parameter pack in T is + // a template parameter pack; each template parameter pack in T is // expanded by the function parameter pack. // // We represent function parameter packs as function parameters whose // type is a pack expansion. if (!T->containsUnexpandedParameterPack()) { - S.Diag(D.getEllipsisLoc(), + S.Diag(D.getEllipsisLoc(), diag::err_function_parameter_pack_without_parameter_packs) << T << D.getSourceRange(); D.setEllipsisLoc(SourceLocation()); @@ -2604,10 +2721,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, T = Context.getPackExpansionType(T, llvm::Optional<unsigned>()); } break; - + case Declarator::TemplateParamContext: // C++0x [temp.param]p15: - // If a template-parameter is a [...] is a parameter-declaration that + // If a template-parameter is a [...] is a parameter-declaration that // declares a parameter pack (8.3.5), then the template-parameter is a // template parameter pack (14.5.3). // @@ -2622,7 +2739,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, ? diag::warn_cxx98_compat_variadic_templates : diag::ext_variadic_templates); break; - + case Declarator::FileContext: case Declarator::KNRTypeListContext: case Declarator::ObjCParameterContext: // FIXME: special diagnostic here? @@ -2675,7 +2792,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S) { if (D.isPrototypeContext() && getLangOpts().ObjCAutoRefCount) inferARCWriteback(state, T); - + return GetFullTypeForDeclarator(state, T, ReturnTypeInfo); } @@ -2700,7 +2817,7 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state, DeclaratorChunk &chunk = D.getTypeObject(chunkIndex); for (const AttributeList *attr = chunk.getAttrs(); attr; attr = attr->getNext()) - if (attr->getKind() == AttributeList::AT_objc_ownership) + if (attr->getKind() == AttributeList::AT_ObjCOwnership) return; const char *attrStr = 0; @@ -2718,14 +2835,13 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state, .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(), /*scope*/ 0, SourceLocation(), &S.Context.Idents.get(attrStr), SourceLocation(), - /*args*/ 0, 0, - /*declspec*/ false, /*C++0x*/ false); + /*args*/ 0, 0, AttributeList::AS_GNU); spliceAttrIntoList(*attr, chunk.getAttrListRef()); // TODO: mark whether we did this inference? } -/// \brief Used for transfering ownership in casts resulting in l-values. +/// \brief Used for transferring ownership in casts resulting in l-values. static void transferARCOwnership(TypeProcessingState &state, QualType &declSpecTy, Qualifiers::ObjCLifetime ownership) { @@ -2763,7 +2879,7 @@ static void transferARCOwnership(TypeProcessingState &state, if (inner == -1) return; - DeclaratorChunk &chunk = D.getTypeObject(inner); + DeclaratorChunk &chunk = D.getTypeObject(inner); if (chunk.Kind == DeclaratorChunk::Pointer) { if (declSpecTy->isObjCRetainableType()) return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership); @@ -2797,33 +2913,33 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) { static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { switch (kind) { case AttributedType::attr_address_space: - return AttributeList::AT_address_space; + return AttributeList::AT_AddressSpace; case AttributedType::attr_regparm: - return AttributeList::AT_regparm; + return AttributeList::AT_Regparm; case AttributedType::attr_vector_size: - return AttributeList::AT_vector_size; + return AttributeList::AT_VectorSize; case AttributedType::attr_neon_vector_type: - return AttributeList::AT_neon_vector_type; + return AttributeList::AT_NeonVectorType; case AttributedType::attr_neon_polyvector_type: - return AttributeList::AT_neon_polyvector_type; + return AttributeList::AT_NeonPolyVectorType; case AttributedType::attr_objc_gc: - return AttributeList::AT_objc_gc; + return AttributeList::AT_ObjCGC; case AttributedType::attr_objc_ownership: - return AttributeList::AT_objc_ownership; + return AttributeList::AT_ObjCOwnership; case AttributedType::attr_noreturn: - return AttributeList::AT_noreturn; + return AttributeList::AT_NoReturn; case AttributedType::attr_cdecl: - return AttributeList::AT_cdecl; + return AttributeList::AT_CDecl; case AttributedType::attr_fastcall: - return AttributeList::AT_fastcall; + return AttributeList::AT_FastCall; case AttributedType::attr_stdcall: - return AttributeList::AT_stdcall; + return AttributeList::AT_StdCall; case AttributedType::attr_thiscall: - return AttributeList::AT_thiscall; + return AttributeList::AT_ThisCall; case AttributedType::attr_pascal: - return AttributeList::AT_pascal; + return AttributeList::AT_Pascal; case AttributedType::attr_pcs: - return AttributeList::AT_pcs; + return AttributeList::AT_Pcs; } llvm_unreachable("unexpected attribute kind!"); } @@ -2856,7 +2972,7 @@ namespace { const DeclSpec &DS; public: - TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS) + TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS) : Context(Context), DS(DS) {} void VisitAttributedTypeLoc(AttributedTypeLoc TL) { @@ -2871,6 +2987,10 @@ namespace { } void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { TL.setNameLoc(DS.getTypeSpecTypeLoc()); + // FIXME. We should have DS.getTypeSpecTypeEndLoc(). But, it requires + // addition field. What we have is good enough for dispay of location + // of 'fixit' on interface name. + TL.setNameEndLoc(DS.getLocEnd()); } void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { // Handle the base type, which might not have been written explicitly. @@ -3000,7 +3120,7 @@ namespace { void VisitAtomicTypeLoc(AtomicTypeLoc TL) { TL.setKWLoc(DS.getTypeSpecTypeLoc()); TL.setParensRange(DS.getTypeofParensRange()); - + TypeSourceInfo *TInfo = 0; Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc()); @@ -3104,7 +3224,7 @@ namespace { assert(Chunk.Kind == DeclaratorChunk::Function); TL.setLocalRangeBegin(Chunk.Loc); TL.setLocalRangeEnd(Chunk.EndLoc); - TL.setTrailingReturn(!!Chunk.Fun.TrailingReturnType); + TL.setTrailingReturn(Chunk.Fun.hasTrailingReturnType()); const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun; for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) { @@ -3142,9 +3262,9 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, // Handle parameter packs whose type is a pack expansion. if (isa<PackExpansionType>(T)) { cast<PackExpansionTypeLoc>(CurrTL).setEllipsisLoc(D.getEllipsisLoc()); - CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); + CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); } - + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { while (isa<AttributedTypeLoc>(CurrTL)) { AttributedTypeLoc TL = cast<AttributedTypeLoc>(CurrTL); @@ -3155,7 +3275,7 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL); CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); } - + // If we have different source information for the return type, use // that. This really only applies to C++ conversion functions. if (ReturnTypeInfo) { @@ -3165,7 +3285,7 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, } else { TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL); } - + return TInfo; } @@ -3174,7 +3294,7 @@ ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) { // FIXME: LocInfoTypes are "transient", only needed for passing to/from Parser // and Sema during declaration parsing. Try deallocating/caching them when // it's appropriate, instead of allocating them and keeping them around. - LocInfoType *LocT = (LocInfoType*)BumpAlloc.Allocate(sizeof(LocInfoType), + LocInfoType *LocT = (LocInfoType*)BumpAlloc.Allocate(sizeof(LocInfoType), TypeAlignment); new (LocT) LocInfoType(T, TInfo); assert(LocT->getTypeClass() != T->getTypeClass() && @@ -3304,13 +3424,13 @@ static bool hasDirectOwnershipQualifier(QualType type) { // X *__strong (...) } else if (const ParenType *paren = dyn_cast<ParenType>(type)) { type = paren->getInnerType(); - + // That's it for things we want to complain about. In particular, // we do not want to look through typedefs, typeof(expr), // typeof(type), or any other way that the type is somehow // abstracted. } else { - + return false; } } @@ -3439,8 +3559,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, attr.setInvalid(); return true; } - - // Forbid __weak for class objects marked as + + // Forbid __weak for class objects marked as // objc_arc_weak_reference_unavailable if (lifetime == Qualifiers::OCL_Weak) { QualType T = type; @@ -3450,12 +3570,12 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl(); if (Class->isArcWeakrefUnavailable()) { S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class); - S.Diag(ObjT->getInterfaceDecl()->getLocation(), + S.Diag(ObjT->getInterfaceDecl()->getLocation(), diag::note_class_declared); } } } - + return true; } @@ -3654,7 +3774,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, FunctionTypeUnwrapper unwrapped(S, type); - if (attr.getKind() == AttributeList::AT_noreturn) { + if (attr.getKind() == AttributeList::AT_NoReturn) { if (S.CheckNoReturnAttr(attr)) return true; @@ -3670,7 +3790,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, // ns_returns_retained is not always a type attribute, but if we got // here, we're treating it as one right now. - if (attr.getKind() == AttributeList::AT_ns_returns_retained) { + if (attr.getKind() == AttributeList::AT_NSReturnsRetained) { assert(S.getLangOpts().ObjCAutoRefCount && "ns_returns_retained treated as type attribute in non-ARC"); if (attr.getNumArgs()) return true; @@ -3685,7 +3805,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, return true; } - if (attr.getKind() == AttributeList::AT_regparm) { + if (attr.getKind() == AttributeList::AT_Regparm) { unsigned value; if (S.CheckRegparmAttr(attr, value)) return true; @@ -3705,7 +3825,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, return true; } - FunctionType::ExtInfo EI = + FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withRegParm(value); type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); return true; @@ -3860,11 +3980,11 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, /// \brief Process the OpenCL-like ext_vector_type attribute when it occurs on /// a type. -static void HandleExtVectorTypeAttr(QualType &CurType, - const AttributeList &Attr, +static void HandleExtVectorTypeAttr(QualType &CurType, + const AttributeList &Attr, Sema &S) { Expr *sizeExpr; - + // Special case where the argument is a template id. if (Attr.getParameterName()) { CXXScopeSpec SS; @@ -3876,7 +3996,7 @@ static void HandleExtVectorTypeAttr(QualType &CurType, id, false, false); if (Size.isInvalid()) return; - + sizeExpr = Size.get(); } else { // check the attribute arguments. @@ -3886,7 +4006,7 @@ static void HandleExtVectorTypeAttr(QualType &CurType, } sizeExpr = Attr.getArg(0); } - + // Create the vector type. QualType T = S.BuildExtVectorType(CurType, sizeExpr, Attr.getLoc()); if (!T.isNull()) @@ -3973,12 +4093,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, switch (attr.getKind()) { default: break; - case AttributeList::AT_may_alias: + case AttributeList::AT_MayAlias: // FIXME: This attribute needs to actually be handled, but if we ignore // it it breaks large amounts of Linux software. attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_address_space: + case AttributeList::AT_AddressSpace: HandleAddressSpaceTypeAttribute(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); break; @@ -3987,35 +4107,42 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, distributeObjCPointerTypeAttr(state, attr, type); attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_vector_size: + case AttributeList::AT_VectorSize: HandleVectorSizeAttr(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_ext_vector_type: + case AttributeList::AT_ExtVectorType: if (state.getDeclarator().getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef) HandleExtVectorTypeAttr(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_neon_vector_type: + case AttributeList::AT_NeonVectorType: HandleNeonVectorTypeAttr(type, attr, state.getSema(), VectorType::NeonVector, "neon_vector_type"); attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_neon_polyvector_type: + case AttributeList::AT_NeonPolyVectorType: HandleNeonVectorTypeAttr(type, attr, state.getSema(), VectorType::NeonPolyVector, "neon_polyvector_type"); attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_opencl_image_access: + case AttributeList::AT_OpenCLImageAccess: HandleOpenCLImageAccessAttribute(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_ns_returns_retained: + case AttributeList::AT_Win64: + case AttributeList::AT_Ptr32: + case AttributeList::AT_Ptr64: + // FIXME: don't ignore these + attr.setUsedAsTypeAttr(); + break; + + case AttributeList::AT_NSReturnsRetained: if (!state.getSema().getLangOpts().ObjCAutoRefCount) - break; + break; // fallthrough into the function attrs FUNCTION_TYPE_ATTRS_CASELIST: @@ -4043,14 +4170,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, /// case of a reference type, the referred-to type). /// /// \param E The expression whose type is required to be complete. -/// \param PD The partial diagnostic that will be printed out if the type cannot -/// be completed. +/// \param Diagnoser The object that will emit a diagnostic if the type is +/// incomplete. /// /// \returns \c true if the type of \p E is incomplete and diagnosed, \c false /// otherwise. -bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD, - std::pair<SourceLocation, - PartialDiagnostic> Note) { +bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser){ QualType T = E->getType(); // Fast path the case where the type is already complete. @@ -4065,7 +4190,7 @@ bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD, if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { if (Var->isStaticDataMember() && Var->getInstantiatedFromStaticDataMember()) { - + MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); assert(MSInfo && "Missing member specialization information?"); if (MSInfo->getTemplateSpecializationKind() @@ -4073,15 +4198,15 @@ bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD, // If we don't already have a point of instantiation, this is it. if (MSInfo->getPointOfInstantiation().isInvalid()) { MSInfo->setPointOfInstantiation(E->getLocStart()); - - // This is a modification of an existing AST node. Notify + + // This is a modification of an existing AST node. Notify // listeners. if (ASTMutationListener *L = getASTMutationListener()) L->StaticDataMemberInstantiated(Var); } - + InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var); - + // Update the type to the newly instantiated definition's type both // here and within the expression. if (VarDecl *Def = Var->getDefinition()) { @@ -4091,7 +4216,7 @@ bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD, E->setType(T); } } - + // We still go on to try to complete the type independently, as it // may also require instantiations or diagnostics if it remains // incomplete. @@ -4107,7 +4232,26 @@ bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD, if (const ReferenceType *Ref = T->getAs<ReferenceType>()) T = Ref->getPointeeType(); - return RequireCompleteType(E->getExprLoc(), T, PD, Note); + return RequireCompleteType(E->getExprLoc(), T, Diagnoser); +} + +namespace { + struct TypeDiagnoserDiag : Sema::TypeDiagnoser { + unsigned DiagID; + + TypeDiagnoserDiag(unsigned DiagID) + : Sema::TypeDiagnoser(DiagID == 0), DiagID(DiagID) {} + + virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { + if (Suppressed) return; + S.Diag(Loc, DiagID) << T; + } + }; +} + +bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) { + TypeDiagnoserDiag Diagnoser(DiagID); + return RequireCompleteExprType(E, Diagnoser); } /// @brief Ensure that the type T is a complete type. @@ -4125,17 +4269,10 @@ bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD, /// /// @param T The type that this routine is examining for completeness. /// -/// @param PD The partial diagnostic that will be printed out if T is not a -/// complete type. -/// /// @returns @c true if @p T is incomplete and a diagnostic was emitted, /// @c false otherwise. bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD, - std::pair<SourceLocation, - PartialDiagnostic> Note) { - unsigned diag = PD.getDiagID(); - + 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 @@ -4148,9 +4285,9 @@ 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 (diag != 0 && Def && !LookupResult::isVisible(Def)) { + if (!Diagnoser.Suppressed && Def && !LookupResult::isVisible(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 + // emitted the error once for this type. There's no usefulness in // repeating the diagnostic. // FIXME: Add a Fix-It that imports the corresponding module or includes // the header. @@ -4159,13 +4296,13 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, Diag(Def->getLocation(), diag::note_previous_definition); } } - + return false; } const TagType *Tag = T->getAs<TagType>(); const ObjCInterfaceType *IFace = 0; - + if (Tag) { // Avoid diagnosing invalid decls as incomplete. if (Tag->getDecl()->isInvalidDecl()) @@ -4182,7 +4319,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, // Avoid diagnosing invalid decls as incomplete. if (IFace->getDecl()->isInvalidDecl()) return true; - + // Give the external AST source a chance to complete the type. if (IFace->getDecl()->hasExternalLexicalStorage()) { Context.getExternalSource()->CompleteType(IFace->getDecl()); @@ -4190,7 +4327,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, return false; } } - + // If we have a class template specialization or a class member of a // class template specialization, or an array with known size of such, // try to instantiate it. @@ -4204,7 +4341,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec, TSK_ImplicitInstantiation, - /*Complain=*/diag != 0); + /*Complain=*/!Diagnoser.Suppressed); } else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Record->getDecl())) { CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass(); @@ -4216,21 +4353,17 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, return InstantiateClass(Loc, Rec, Pattern, getTemplateInstantiationArgs(Rec), TSK_ImplicitInstantiation, - /*Complain=*/diag != 0); + /*Complain=*/!Diagnoser.Suppressed); } } } - if (diag == 0) + if (Diagnoser.Suppressed) return true; - + // We have an incomplete type. Produce a diagnostic. - Diag(Loc, PD) << T; - - // If we have a note, produce it. - if (!Note.first.isInvalid()) - Diag(Note.first, Note.second); - + Diagnoser.diagnose(*this, Loc, T); + // If the type was a forward declaration of a class/struct/union // type, produce a note. if (Tag && !Tag->getDecl()->isInvalidDecl()) @@ -4238,7 +4371,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, Tag->isBeingDefined() ? diag::note_type_being_defined : diag::note_forward_declaration) << QualType(Tag, 0); - + // If the Objective-C class was a forward declaration, produce a note. if (IFace && !IFace->getDecl()->isInvalidDecl()) Diag(IFace->getDecl()->getLocation(), diag::note_forward_class); @@ -4247,15 +4380,9 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, } bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD) { - return RequireCompleteType(Loc, T, PD, - std::make_pair(SourceLocation(), PDiag(0))); -} - -bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID) { - return RequireCompleteType(Loc, T, PDiag(DiagID), - std::make_pair(SourceLocation(), PDiag(0))); + TypeDiagnoserDiag Diagnoser(DiagID); + return RequireCompleteType(Loc, T, Diagnoser); } /// @brief Ensure that the type T is a literal type. @@ -4272,13 +4399,12 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, /// /// @param T The type that this routine is examining for literalness. /// -/// @param PD The partial diagnostic that will be printed out if T is not a -/// literal type. +/// @param Diagnoser Emits a diagnostic if T is not a literal type. /// /// @returns @c true if @p T is not a literal type and a diagnostic was emitted, /// @c false otherwise. bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD) { + TypeDiagnoser &Diagnoser) { assert(!T->isDependentType() && "type should not be dependent"); QualType ElemType = Context.getBaseElementType(T); @@ -4287,10 +4413,10 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, if (T->isLiteralType()) return false; - if (PD.getDiagID() == 0) + if (Diagnoser.Suppressed) return true; - Diag(Loc, PD) << T; + Diagnoser.diagnose(*this, Loc, T); if (T->isVariableArrayType()) return true; @@ -4301,9 +4427,13 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - // FIXME: Better diagnostic for incomplete class? - if (!RD->isCompleteDefinition()) + // A partially-defined class type can't be a literal type, because a literal + // class type must have a trivial destructor (which can't be checked until + // the class definition is complete). + if (!RD->isCompleteDefinition()) { + RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T); return true; + } // If the class has virtual base classes, then it's not an aggregate, and // cannot have any constexpr constructors or a trivial default constructor, @@ -4331,11 +4461,11 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, } for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); I != E; ++I) { - if (!(*I)->getType()->isLiteralType() || - (*I)->getType().isVolatileQualified()) { - Diag((*I)->getLocation(), diag::note_non_literal_field) - << RD << (*I) << (*I)->getType() - << (*I)->getType().isVolatileQualified(); + if (!I->getType()->isLiteralType() || + I->getType().isVolatileQualified()) { + Diag(I->getLocation(), diag::note_non_literal_field) + << RD << *I << I->getType() + << I->getType().isVolatileQualified(); return true; } } @@ -4355,6 +4485,11 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, return true; } +bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) { + TypeDiagnoserDiag Diagnoser(DiagID); + return RequireLiteralType(Loc, T, Diagnoser); +} + /// \brief Retrieve a version of the type 'T' that is elaborated by Keyword /// and qualified by the nested-name-specifier contained in SS. QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword, @@ -4396,8 +4531,8 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) { // The type denoted by decltype(e) is defined as follows: // // - if e is an unparenthesized id-expression or an unparenthesized class - // member access (5.2.5), decltype(e) is the type of the entity named - // by e. If there is no such entity, or if e names a set of overloaded + // member access (5.2.5), decltype(e) is the type of the entity named + // by e. If there is no such entity, or if e names a set of overloaded // functions, the program is ill-formed; if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) @@ -4407,7 +4542,7 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) { if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) return FD->getType(); } - + // C++11 [expr.lambda.prim]p18: // Every occurrence of decltype((x)) where x is a possibly // parenthesized id-expression that names an entity of automatic @@ -4433,16 +4568,16 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) { // [...] QualType T = E->getType(); switch (E->getValueKind()) { - // - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the + // - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the // type of e; case VK_XValue: T = S.Context.getRValueReferenceType(T); break; - // - otherwise, if e is an lvalue, decltype(e) is T&, where T is the + // - otherwise, if e is an lvalue, decltype(e) is T&, where T is the // type of e; case VK_LValue: T = S.Context.getLValueReferenceType(T); break; // - otherwise, decltype(e) is the type of e. case VK_RValue: break; } - + return T; } @@ -4450,7 +4585,7 @@ QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) { ExprResult ER = CheckPlaceholderExpr(E); if (ER.isInvalid()) return QualType(); E = ER.take(); - + return Context.getDecltypeType(E, getDecltypeForExpr(*this, E)); } @@ -4482,8 +4617,7 @@ QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) { if (!T->isDependentType()) { // FIXME: It isn't entirely clear whether incomplete atomic types // are allowed or not; for simplicity, ban them for the moment. - if (RequireCompleteType(Loc, T, - PDiag(diag::err_atomic_specifier_bad_type) << 0)) + if (RequireCompleteType(Loc, T, diag::err_atomic_specifier_bad_type, 0)) return QualType(); int DisallowedKind = -1; |