From 2865474261a608c7873b87ba4af110d17907896d Mon Sep 17 00:00:00 2001 From: John McCall Date: Sat, 5 Jun 2010 06:41:15 +0000 Subject: [PATCH] Simplify the methods for creating a pointer, reference, member-pointer, or block-pointer type by removing the qualifiers parameter. Introduce a method to perform semantic checking when adding qualifiers to a type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105526 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/Sema.h | 12 ++- lib/Sema/SemaType.cpp | 197 ++++++++++++++++----------------------- lib/Sema/TreeTransform.h | 18 ++-- 3 files changed, 98 insertions(+), 129 deletions(-) diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 064d34316e..10ff5ad8b9 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -718,9 +718,13 @@ public: // QualType adjustParameterType(QualType T); - QualType BuildPointerType(QualType T, unsigned Quals, + QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs); + QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVR) { + return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR)); + } + QualType BuildPointerType(QualType T, SourceLocation Loc, DeclarationName Entity); - QualType BuildReferenceType(QualType T, bool LValueRef, unsigned Quals, + QualType BuildReferenceType(QualType T, bool LValueRef, SourceLocation Loc, DeclarationName Entity); QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, Expr *ArraySize, unsigned Quals, @@ -732,9 +736,9 @@ public: bool Variadic, unsigned Quals, SourceLocation Loc, DeclarationName Entity); QualType BuildMemberPointerType(QualType T, QualType Class, - unsigned Quals, SourceLocation Loc, + SourceLocation Loc, DeclarationName Entity); - QualType BuildBlockPointerType(QualType T, unsigned Quals, + QualType BuildBlockPointerType(QualType T, SourceLocation Loc, DeclarationName Entity); TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S, TagDecl **OwnedDecl = 0); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 91452a86a0..8242f61897 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -472,12 +472,49 @@ static std::string getPrintableNameForEntity(DeclarationName Entity) { return "type name"; } +QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, + Qualifiers Qs) { + // Enforce C99 6.7.3p2: "Types other than pointer types derived from + // object or incomplete types shall not be restrict-qualified." + if (Qs.hasRestrict()) { + unsigned DiagID = 0; + QualType ProblemTy; + + const Type *Ty = T->getCanonicalTypeInternal().getTypePtr(); + if (const ReferenceType *RTy = dyn_cast(Ty)) { + if (!RTy->getPointeeType()->isIncompleteOrObjectType()) { + DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; + ProblemTy = T->getAs()->getPointeeType(); + } + } else if (const PointerType *PTy = dyn_cast(Ty)) { + if (!PTy->getPointeeType()->isIncompleteOrObjectType()) { + DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; + ProblemTy = T->getAs()->getPointeeType(); + } + } else if (const MemberPointerType *PTy = dyn_cast(Ty)) { + if (!PTy->getPointeeType()->isIncompleteOrObjectType()) { + DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; + ProblemTy = T->getAs()->getPointeeType(); + } + } else if (!Ty->isDependentType()) { + // FIXME: this deserves a proper diagnostic + DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; + ProblemTy = T; + } + + if (DiagID) { + Diag(Loc, DiagID) << ProblemTy; + Qs.removeRestrict(); + } + } + + return Context.getQualifiedType(T, Qs); +} + /// \brief Build a pointer type. /// /// \param T The type to which we'll be building a pointer. /// -/// \param Quals The cvr-qualifiers to be applied to the pointer type. -/// /// \param Loc The location of the entity whose type involves this /// pointer type or, if there is no such entity, the location of the /// type that will have pointer type. @@ -487,7 +524,7 @@ static std::string getPrintableNameForEntity(DeclarationName Entity) { /// /// \returns A suitable pointer type, if there are no /// errors. Otherwise, returns a NULL type. -QualType Sema::BuildPointerType(QualType T, unsigned Quals, +QualType Sema::BuildPointerType(QualType T, SourceLocation Loc, DeclarationName Entity) { if (T->isReferenceType()) { // C++ 8.3.2p4: There shall be no ... pointers to references ... @@ -496,28 +533,16 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals, return QualType(); } - Qualifiers Qs = Qualifiers::fromCVRMask(Quals); - - // Enforce C99 6.7.3p2: "Types other than pointer types derived from - // object or incomplete types shall not be restrict-qualified." - if (Qs.hasRestrict() && !T->isIncompleteOrObjectType()) { - Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee) - << T; - Qs.removeRestrict(); - } - assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType"); // Build the pointer type. - return Context.getQualifiedType(Context.getPointerType(T), Qs); + return Context.getPointerType(T); } /// \brief Build a reference type. /// /// \param T The type to which we'll be building a reference. /// -/// \param CVR The cvr-qualifiers to be applied to the reference type. -/// /// \param Loc The location of the entity whose type involves this /// reference type or, if there is no such entity, the location of the /// type that will have reference type. @@ -528,10 +553,8 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals, /// \returns A suitable reference type, if there are no /// errors. Otherwise, returns a NULL type. QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, - unsigned CVR, SourceLocation Loc, + SourceLocation Loc, DeclarationName Entity) { - Qualifiers Quals = Qualifiers::fromCVRMask(CVR); - bool LValueRef = SpelledAsLValue || T->getAs(); // C++0x [dcl.typedef]p9: If a typedef TD names a type that is a @@ -562,31 +585,10 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, return QualType(); } - // Enforce C99 6.7.3p2: "Types other than pointer types derived from - // object or incomplete types shall not be restrict-qualified." - if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) { - Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee) - << T; - Quals.removeRestrict(); - } - - // C++ [dcl.ref]p1: - // [...] Cv-qualified references are ill-formed except when the - // cv-qualifiers are introduced through the use of a typedef - // (7.1.3) or of a template type argument (14.3), in which case - // the cv-qualifiers are ignored. - // - // We diagnose extraneous cv-qualifiers for the non-typedef, - // non-template type argument case within the parser. Here, we just - // ignore any extraneous cv-qualifiers. - Quals.removeConst(); - Quals.removeVolatile(); - // Handle restrict on references. if (LValueRef) - return Context.getQualifiedType( - Context.getLValueReferenceType(T, SpelledAsLValue), Quals); - return Context.getQualifiedType(Context.getRValueReferenceType(T), Quals); + return Context.getLValueReferenceType(T, SpelledAsLValue); + return Context.getRValueReferenceType(T); } /// \brief Build an array type. @@ -597,9 +599,6 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, /// /// \param ArraySize Expression describing the size of the array. /// -/// \param Quals The cvr-qualifiers to be applied to the array's -/// element type. -/// /// \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. @@ -846,10 +845,8 @@ QualType Sema::BuildFunctionType(QualType T, /// \returns a member pointer type, if successful, or a NULL type if there was /// an error. QualType Sema::BuildMemberPointerType(QualType T, QualType Class, - unsigned CVR, SourceLocation Loc, + SourceLocation Loc, DeclarationName Entity) { - Qualifiers Quals = Qualifiers::fromCVRMask(CVR); - // Verify that we're not building a pointer to pointer to function with // exception specification. if (CheckDistantExceptionSpec(T)) { @@ -877,24 +874,12 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, return QualType(); } - // Enforce C99 6.7.3p2: "Types other than pointer types derived from - // object or incomplete types shall not be restrict-qualified." - if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) { - Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee) - << T; - - // FIXME: If we're doing this as part of template instantiation, - // we should return immediately. - Quals.removeRestrict(); - } - if (!Class->isDependentType() && !Class->isRecordType()) { Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class; return QualType(); } - return Context.getQualifiedType( - Context.getMemberPointerType(T, Class.getTypePtr()), Quals); + return Context.getMemberPointerType(T, Class.getTypePtr()); } /// \brief Build a block pointer type. @@ -912,7 +897,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, /// /// \returns A suitable block pointer type, if there are no /// errors. Otherwise, returns a NULL type. -QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR, +QualType Sema::BuildBlockPointerType(QualType T, SourceLocation Loc, DeclarationName Entity) { if (!T->isFunctionType()) { @@ -920,8 +905,7 @@ QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR, return QualType(); } - Qualifiers Quals = Qualifiers::fromCVRMask(CVR); - return Context.getQualifiedType(Context.getBlockPointerType(T), Quals); + return Context.getBlockPointerType(T); } QualType Sema::GetTypeFromParser(TypeTy *Ty, TypeSourceInfo **TInfo) { @@ -1057,8 +1041,9 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (!LangOpts.Blocks) Diag(DeclType.Loc, diag::err_blocks_disable); - T = BuildBlockPointerType(T, DeclType.Cls.TypeQuals, D.getIdentifierLoc(), - Name); + T = BuildBlockPointerType(T, D.getIdentifierLoc(), Name); + if (DeclType.Cls.TypeQuals) + T = BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals); break; case DeclaratorChunk::Pointer: // Verify that we're not building a pointer to pointer to function with @@ -1070,15 +1055,15 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } if (getLangOptions().ObjC1 && T->getAs()) { T = Context.getObjCObjectPointerType(T); - T = Context.getCVRQualifiedType(T, DeclType.Ptr.TypeQuals); + if (DeclType.Ptr.TypeQuals) + T = BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals); break; } - T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name); + T = BuildPointerType(T, DeclType.Loc, Name); + if (DeclType.Ptr.TypeQuals) + T = BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals); break; case DeclaratorChunk::Reference: { - Qualifiers Quals; - if (DeclType.Ref.HasRestrict) Quals.addRestrict(); - // Verify that we're not building a reference to pointer to function with // exception specification. if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) { @@ -1086,8 +1071,11 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, D.setInvalidType(true); // Build the type anyway. } - T = BuildReferenceType(T, DeclType.Ref.LValueRef, Quals, - DeclType.Loc, Name); + T = BuildReferenceType(T, DeclType.Ref.LValueRef, DeclType.Loc, Name); + + Qualifiers Quals; + if (DeclType.Ref.HasRestrict) + T = BuildQualifiedType(T, DeclType.Loc, Qualifiers::Restrict); break; } case DeclaratorChunk::Array: { @@ -1152,29 +1140,14 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) Diag(FTI.getThrowLoc(), diag::err_exception_spec_in_typedef); - if (FTI.NumArgs == 0) { - if (getLangOptions().CPlusPlus) { - // C++ 8.3.5p2: If the parameter-declaration-clause is empty, the - // function takes no arguments. - llvm::SmallVector Exceptions; - Exceptions.reserve(FTI.NumExceptions); - for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) { - // FIXME: Preserve type source info. - QualType ET = GetTypeFromParser(FTI.Exceptions[ei].Ty); - // Check that the type is valid for an exception spec, and drop it - // if not. - if (!CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range)) - Exceptions.push_back(ET); - } - T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, FTI.TypeQuals, - FTI.hasExceptionSpec, - FTI.hasAnyExceptionSpec, - Exceptions.size(), Exceptions.data(), - FunctionType::ExtInfo()); - } else if (FTI.isVariadic) { - // We allow a zero-parameter variadic function in C if the - // function is marked with the "overloadable" - // attribute. Scan for this attribute now. + if (!FTI.NumArgs && !FTI.isVariadic && !getLangOptions().CPlusPlus) { + // Simple void foo(), where the incoming T is the result type. + T = Context.getFunctionNoProtoType(T); + } else { + // We allow a zero-parameter variadic function in C if the + // function is marked with the "overloadable" attribute. Scan + // for this attribute now. + if (!FTI.NumArgs && FTI.isVariadic && !getLangOptions().CPlusPlus) { bool Overloadable = false; for (const AttributeList *Attrs = D.getAttributes(); Attrs; Attrs = Attrs->getNext()) { @@ -1186,21 +1159,19 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (!Overloadable) Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg); - T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); - } else { - // Simple void foo(), where the incoming T is the result type. - T = Context.getFunctionNoProtoType(T); } - } else if (FTI.ArgInfo[0].Param == 0) { - // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function definition. - Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration); - D.setInvalidType(true); - } else { + + if (FTI.NumArgs && FTI.ArgInfo[0].Param == 0) { + // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function definition. + Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration); + D.setInvalidType(true); + break; + } + // Otherwise, we have a function with an argument list that is // potentially variadic. llvm::SmallVector ArgTys; + ArgTys.reserve(FTI.NumArgs); for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { ParmVarDecl *Param = @@ -1276,13 +1247,6 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, break; } case DeclaratorChunk::MemberPointer: - // Verify that we're not building a pointer to pointer to function with - // exception specification. - if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) { - Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec); - D.setInvalidType(true); - // Build the type anyway. - } // The scope spec must refer to a class, or be dependent. QualType ClsType; if (DeclType.Mem.Scope().isInvalid()) { @@ -1321,11 +1285,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } if (!ClsType.isNull()) - T = BuildMemberPointerType(T, ClsType, DeclType.Mem.TypeQuals, - DeclType.Loc, D.getIdentifier()); + T = BuildMemberPointerType(T, ClsType, DeclType.Loc, D.getIdentifier()); if (T.isNull()) { T = Context.IntTy; D.setInvalidType(true); + } else if (DeclType.Mem.TypeQuals) { + T = BuildQualifiedType(T, DeclType.Loc, DeclType.Mem.TypeQuals); } break; } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index a18701e61d..26caaadd49 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2405,11 +2405,11 @@ TreeTransform::TransformQualifiedType(TypeLocBuilder &TLB, if (Result->isFunctionType() || Result->isReferenceType()) return Result; - Result = SemaRef.Context.getQualifiedType(Result, Quals); - - TLB.push(Result); - - // No location information to preserve. + if (!Quals.empty()) { + Result = SemaRef.BuildQualifiedType(Result, T.getBeginLoc(), Quals); + TLB.push(Result); + // No location information to preserve. + } return Result; } @@ -6185,14 +6185,14 @@ TreeTransform::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { template QualType TreeTransform::RebuildPointerType(QualType PointeeType, SourceLocation Star) { - return SemaRef.BuildPointerType(PointeeType, Qualifiers(), Star, + return SemaRef.BuildPointerType(PointeeType, Star, getDerived().getBaseEntity()); } template QualType TreeTransform::RebuildBlockPointerType(QualType PointeeType, SourceLocation Star) { - return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(), Star, + return SemaRef.BuildBlockPointerType(PointeeType, Star, getDerived().getBaseEntity()); } @@ -6201,7 +6201,7 @@ QualType TreeTransform::RebuildReferenceType(QualType ReferentType, bool WrittenAsLValue, SourceLocation Sigil) { - return SemaRef.BuildReferenceType(ReferentType, WrittenAsLValue, Qualifiers(), + return SemaRef.BuildReferenceType(ReferentType, WrittenAsLValue, Sigil, getDerived().getBaseEntity()); } @@ -6210,7 +6210,7 @@ QualType TreeTransform::RebuildMemberPointerType(QualType PointeeType, QualType ClassType, SourceLocation Sigil) { - return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Qualifiers(), + return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Sigil, getDerived().getBaseEntity()); } -- 2.40.0