diff options
-rw-r--r-- | lib/Sema/Sema.h | 7 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 424 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 359 | ||||
-rw-r--r-- | test/SemaTemplate/instantiation-default-1.cpp | 65 |
5 files changed, 485 insertions, 372 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 7875a8183b..7a5a10287f 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -232,6 +232,13 @@ public: // QualType ConvertDeclSpecToType(const DeclSpec &DS); void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL); + QualType BuildPointerType(QualType T, unsigned Quals, + SourceLocation Loc, DeclarationName Entity); + QualType BuildReferenceType(QualType T, unsigned Quals, + SourceLocation Loc, DeclarationName Entity); + QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, + Expr *ArraySize, unsigned Quals, + SourceLocation Loc, DeclarationName Entity); QualType GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip = 0); DeclarationName GetNameForDeclarator(Declarator &D); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index aabbffa4c3..54f1d87cc8 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -766,7 +766,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, TTP->getDeclName()); if (ArgType.isNull()) - break; + return true; ArgLoc = TTP->getDefaultArgumentLoc(); } else if (NonTypeTemplateParmDecl *NTTP diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 1e7569a9b2..f864a50c5e 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -17,283 +17,246 @@ #include "clang/AST/DeclTemplate.h" #include "clang/Parse/DeclSpec.h" #include "clang/Basic/LangOptions.h" +#include "llvm/Support/Compiler.h" using namespace clang; //===----------------------------------------------------------------------===/ // Template Instantiation for Types //===----------------------------------------------------------------------===/ +namespace { + class VISIBILITY_HIDDEN TemplateTypeInstantiator { + Sema &SemaRef; + const TemplateArgument *TemplateArgs; + unsigned NumTemplateArgs; + SourceLocation Loc; + DeclarationName Entity; + + public: + TemplateTypeInstantiator(Sema &SemaRef, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceLocation Loc, + DeclarationName Entity) + : SemaRef(SemaRef), TemplateArgs(TemplateArgs), + NumTemplateArgs(NumTemplateArgs), Loc(Loc), Entity(Entity) { } + + QualType operator()(QualType T) const { return Instantiate(T); } + + QualType Instantiate(QualType T) const; + + // Declare instantiate functions for each type. +#define TYPE(Class, Base) \ + QualType Instantiate##Class##Type(const Class##Type *T, \ + unsigned Quals) const; +#define ABSTRACT_TYPE(Class, Base) +#include "clang/AST/TypeNodes.def" + }; +} -static QualType PerformTypeInstantiation(Sema &SemaRef, - const ExtQualType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator::InstantiateExtQualType(const ExtQualType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate ExtQualType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const BuiltinType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator::InstantiateBuiltinType(const BuiltinType *T, + unsigned Quals) const { assert(false && "BuiltinType is never dependent and cannot be instantiated"); - return QualType(T, CVR); + return QualType(T, Quals); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const FixedWidthIntType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator:: +InstantiateFixedWidthIntType(const FixedWidthIntType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate FixedWidthIntType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const ComplexType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator::InstantiateComplexType(const ComplexType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate ComplexType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const PointerType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { - // FIXME: Implement this - assert(false && "Cannot instantiate PointerType yet"); - return QualType(); +QualType +TemplateTypeInstantiator::InstantiatePointerType(const PointerType *T, + unsigned Quals) const { + QualType PointeeType = Instantiate(T->getPointeeType()); + if (PointeeType.isNull()) + return QualType(); + + return SemaRef.BuildPointerType(PointeeType, Quals, Loc, Entity); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const BlockPointerType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator::InstantiateBlockPointerType(const BlockPointerType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate BlockPointerType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const ReferenceType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { - // FIXME: Implement this - assert(false && "Cannot instantiate ReferenceType yet"); - return QualType(); +QualType +TemplateTypeInstantiator::InstantiateReferenceType(const ReferenceType *T, + unsigned Quals) const { + QualType ReferentType = Instantiate(T->getPointeeType()); + if (ReferentType.isNull()) + return QualType(); + + return SemaRef.BuildReferenceType(ReferentType, Quals, Loc, Entity); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const MemberPointerType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator:: +InstantiateMemberPointerType(const MemberPointerType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate MemberPointerType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const ConstantArrayType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { - // FIXME: Implement this - assert(false && "Cannot instantiate ConstantArrayType yet"); - return QualType(); +QualType +TemplateTypeInstantiator:: +InstantiateConstantArrayType(const ConstantArrayType *T, + unsigned Quals) const { + QualType ElementType = Instantiate(T->getElementType()); + if (ElementType.isNull()) + return ElementType; + + // Build a temporary integer literal to specify the size for + // BuildArrayType. Since we have already checked the size as part of + // creating the dependent array type in the first place, we know + // there aren't any errors. + IntegerLiteral ArraySize(T->getSize(), SemaRef.Context.IntTy, Loc); + return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(), + &ArraySize, T->getIndexTypeQualifier(), + Loc, Entity); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const IncompleteArrayType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { - // FIXME: Implement this - assert(false && "Cannot instantiate IncompleteArrayType yet"); - return QualType(); +QualType +TemplateTypeInstantiator:: +InstantiateIncompleteArrayType(const IncompleteArrayType *T, + unsigned Quals) const { + QualType ElementType = Instantiate(T->getElementType()); + if (ElementType.isNull()) + return ElementType; + + return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(), + 0, T->getIndexTypeQualifier(), + Loc, Entity); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const VariableArrayType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator:: +InstantiateVariableArrayType(const VariableArrayType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate VariableArrayType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const DependentSizedArrayType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator:: +InstantiateDependentSizedArrayType(const DependentSizedArrayType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate DependentSizedArrayType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const VectorType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate VectorType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const ExtVectorType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator::InstantiateExtVectorType(const ExtVectorType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate ExtVectorType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const FunctionProtoType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator:: +InstantiateFunctionProtoType(const FunctionProtoType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate FunctionProtoType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const FunctionNoProtoType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator:: +InstantiateFunctionNoProtoType(const FunctionNoProtoType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate FunctionNoProtoType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const TypedefType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate TypedefType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const TypeOfExprType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator::InstantiateTypeOfExprType(const TypeOfExprType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate TypeOfExprType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const TypeOfType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator::InstantiateTypeOfType(const TypeOfType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate TypeOfType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const RecordType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate RecordType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const CXXRecordType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator::InstantiateCXXRecordType(const CXXRecordType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate CXXRecordType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const EnumType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate EnumType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const TemplateTypeParmType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator:: +InstantiateTemplateTypeParmType(const TemplateTypeParmType *T, + unsigned Quals) const { if (T->getDepth() == 0) { // Replace the template type parameter with its corresponding // template argument. @@ -301,7 +264,7 @@ static QualType PerformTypeInstantiation(Sema &SemaRef, assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type && "Template argument kind mismatch"); QualType Result = TemplateArgs[T->getIndex()].getAsType(); - if (Result.isNull() || !CVR) + if (Result.isNull() || !Quals) return Result; // C++ [dcl.ref]p1: @@ -309,10 +272,10 @@ static QualType PerformTypeInstantiation(Sema &SemaRef, // 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. - if (CVR && Result->isReferenceType()) - CVR = 0; + if (Quals && Result->isReferenceType()) + Quals = 0; - return QualType(Result.getTypePtr(), CVR | Result.getCVRQualifiers()); + return QualType(Result.getTypePtr(), Quals | Result.getCVRQualifiers()); } // The template type parameter comes from an inner template (e.g., @@ -321,69 +284,70 @@ static QualType PerformTypeInstantiation(Sema &SemaRef, // parameter with the template "level" reduced by one. return SemaRef.Context.getTemplateTypeParmType(T->getDepth() - 1, T->getIndex(), - T->getName()); + T->getName()) + .getQualifiedType(Quals); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const ClassTemplateSpecializationType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { +QualType +TemplateTypeInstantiator:: +InstantiateClassTemplateSpecializationType( + const ClassTemplateSpecializationType *T, + unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate ClassTemplateSpecializationType yet"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const ObjCInterfaceType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { - // FIXME: Implement this - assert(false && "Cannot instantiate ObjCInterfaceType yet"); +QualType +TemplateTypeInstantiator:: +InstantiateObjCInterfaceType(const ObjCInterfaceType *T, + unsigned Quals) const { + assert(false && "Objective-C types cannot be dependent"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const ObjCQualifiedInterfaceType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { - // FIXME: Implement this - assert(false && "Cannot instantiate ObjCQualifiedInterfaceType yet"); +QualType +TemplateTypeInstantiator:: +InstantiateObjCQualifiedInterfaceType(const ObjCQualifiedInterfaceType *T, + unsigned Quals) const { + assert(false && "Objective-C types cannot be dependent"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const ObjCQualifiedIdType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { - // FIXME: Implement this - assert(false && "Cannot instantiate ObjCQualifiedIdType yet"); +QualType +TemplateTypeInstantiator:: +InstantiateObjCQualifiedIdType(const ObjCQualifiedIdType *T, + unsigned Quals) const { + assert(false && "Objective-C types cannot be dependent"); return QualType(); } -static QualType PerformTypeInstantiation(Sema &SemaRef, - const ObjCQualifiedClassType *T, - unsigned CVR, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation Loc, - DeclarationName Entity) { - // FIXME: Implement this - assert(false && "Cannot instantiate ObjCQualifiedClassType yet"); +QualType +TemplateTypeInstantiator:: +InstantiateObjCQualifiedClassType(const ObjCQualifiedClassType *T, + unsigned Quals) const { + assert(false && "Objective-C types cannot be dependent"); return QualType(); } +/// \brief The actual implementation of Sema::InstantiateType(). +QualType TemplateTypeInstantiator::Instantiate(QualType T) const { + // If T is not a dependent type, there is nothing to do. + if (!T->isDependentType()) + return T; + + switch (T->getTypeClass()) { +#define TYPE(Class, Base) \ + case Type::Class: \ + return Instantiate##Class##Type(cast<Class##Type>(T.getTypePtr()), \ + T.getCVRQualifiers()); +#define ABSTRACT_TYPE(Class, Base) +#include "clang/AST/TypeNodes.def" + } + + assert(false && "Not all types have been decoded for instantiation"); + return QualType(); +} /// \brief Instantiate the type T with a given set of template arguments. /// @@ -422,17 +386,7 @@ QualType Sema::InstantiateType(QualType T, if (!T->isDependentType()) return T; - switch (T->getTypeClass()) { -#define TYPE(Class, Base) \ - case Type::Class: \ - return PerformTypeInstantiation(*this, \ - cast<Class##Type>(T.getTypePtr()), \ - T.getCVRQualifiers(), TemplateArgs, \ - NumTemplateArgs, Loc, Entity); -#define ABSTRACT_TYPE(Class, Base) -#include "clang/AST/TypeNodes.def" - } - - assert(false && "Not all types have been decoded for instantiation"); - return QualType(); + TemplateTypeInstantiator Instantiator(*this, TemplateArgs, NumTemplateArgs, + Loc, Entity); + return Instantiator(T); } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index a1c5dbc4d1..bc2bce3883 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -260,6 +260,215 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) { return Result; } +static std::string getPrintableNameForEntity(DeclarationName Entity) { + if (Entity) + return Entity.getAsString(); + + return "type name"; +} + +/// \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. +/// +/// \param Entity The name of the entity that involves the pointer +/// type, if known. +/// +/// \returns A suitable pointer type, if there are no +/// errors. Otherwise, returns a NULL type. +QualType Sema::BuildPointerType(QualType T, unsigned Quals, + SourceLocation Loc, DeclarationName Entity) { + if (T->isReferenceType()) { + // C++ 8.3.2p4: There shall be no ... pointers to references ... + Diag(Loc, diag::err_illegal_decl_pointer_to_reference) + << getPrintableNameForEntity(Entity); + 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 & QualType::Restrict) && !T->isIncompleteOrObjectType()) { + Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee) + << T; + Quals &= ~QualType::Restrict; + } + + // Build the pointer type. + return Context.getPointerType(T).getQualifiedType(Quals); +} + +/// \brief Build a reference type. +/// +/// \param T The type to which we'll be building a reference. +/// +/// \param Quals 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. +/// +/// \param Entity The name of the entity that involves the reference +/// type, if known. +/// +/// \returns A suitable reference type, if there are no +/// errors. Otherwise, returns a NULL type. +QualType Sema::BuildReferenceType(QualType T, unsigned Quals, + SourceLocation Loc, DeclarationName Entity) { + if (T->isReferenceType()) { + // C++ [dcl.ref]p4: There shall be no references to references. + // + // According to C++ DR 106, references to references are only + // diagnosed when they are written directly (e.g., "int & &"), + // but not when they happen via a typedef: + // + // typedef int& intref; + // typedef intref& intref2; + // + // Parser::ParserDeclaratorInternal diagnoses the case where + // references are written directly; here, we handle the + // collapsing of references-to-references as described in C++ + // DR 106 and amended by C++ DR 540. + return T; + } + + // C++ [dcl.ref]p1: + // A declarator that specifies the type “reference to cv void” + // is ill-formed. + if (T->isVoidType()) { + Diag(Loc, diag::err_reference_to_void); + 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 & QualType::Restrict) && !T->isIncompleteOrObjectType()) { + Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee) + << T; + Quals &= ~QualType::Restrict; + } + + // 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 &= ~QualType::Const; + Quals &= ~QualType::Volatile; + + // Handle restrict on references. + return Context.getReferenceType(T).getQualifiedType(Quals); +} + +/// \brief Build an array type. +/// +/// \param T The type of each element in the array. +/// +/// \param ASM C99 array size modifier (e.g., '*', 'static'). +/// +/// \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. +/// +/// \param Entity The name of the entity that involves the array +/// type, if known. +/// +/// \returns A suitable array type, if there are no errors. Otherwise, +/// returns a NULL type. +QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, + Expr *ArraySize, unsigned Quals, + SourceLocation Loc, DeclarationName Entity) { + // 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]()) + if (DiagnoseIncompleteType(Loc, T, + diag::err_illegal_decl_array_incomplete_type)) + return QualType(); + + if (T->isFunctionType()) { + Diag(Loc, diag::err_illegal_decl_array_of_functions) + << getPrintableNameForEntity(Entity); + return QualType(); + } + + // C++ 8.3.2p4: There shall be no ... arrays of references ... + if (T->isReferenceType()) { + Diag(Loc, diag::err_illegal_decl_array_of_references) + << getPrintableNameForEntity(Entity); + return QualType(); + } + + if (const RecordType *EltTy = T->getAsRecordType()) { + // If the element type is a struct or union that contains a variadic + // array, accept it as a GNU extension: C99 6.7.2.1p2. + if (EltTy->getDecl()->hasFlexibleArrayMember()) + Diag(Loc, diag::ext_flexible_array_in_array) << T; + } else if (T->isObjCInterfaceType()) { + Diag(Loc, diag::warn_objc_array_of_interfaces) << T; + } + + // C99 6.7.5.2p1: The size expression shall have integer type. + if (ArraySize && !ArraySize->isTypeDependent() && + !ArraySize->getType()->isIntegerType()) { + Diag(ArraySize->getLocStart(), diag::err_array_size_non_int) + << ArraySize->getType() << ArraySize->getSourceRange(); + ArraySize->Destroy(Context); + return QualType(); + } + llvm::APSInt ConstVal(32); + if (!ArraySize) { + T = Context.getIncompleteArrayType(T, ASM, Quals); + } else if (ArraySize->isValueDependent()) { + T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals); + } else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) || + (!T->isDependentType() && !T->isConstantSizeType())) { + // Per C99, a variable array is an array with either a non-constant + // size or an element type that has a non-constant-size + T = Context.getVariableArrayType(T, ArraySize, ASM, Quals); + } else { + // C99 6.7.5.2p1: If the expression is a constant expression, it shall + // have a value greater than zero. + if (ConstVal.isSigned()) { + if (ConstVal.isNegative()) { + Diag(ArraySize->getLocStart(), + diag::err_typecheck_negative_array_size) + << ArraySize->getSourceRange(); + return QualType(); + } else if (ConstVal == 0) { + // GCC accepts zero sized static arrays. + Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size) + << ArraySize->getSourceRange(); + } + } + T = Context.getConstantArrayType(T, ConstVal, ASM, Quals); + } + // If this is not C99, extwarn about VLA's and C99 array size modifiers. + if (!getLangOptions().C99) { + if (ArraySize && !ArraySize->isTypeDependent() && + !ArraySize->isValueDependent() && + !ArraySize->isIntegerConstantExpr(Context)) + Diag(Loc, diag::ext_vla); + else if (ASM != ArrayType::Normal || Quals != 0) + Diag(Loc, diag::ext_c99_array_usage); + } + + return T; +} + + /// GetTypeForDeclarator - Convert the type for the specified /// declarator to Type instances. Skip the outermost Skip type /// objects. @@ -309,6 +518,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) { break; } + // The name we're declaring, if any. + DeclarationName Name; + if (D.getIdentifier()) + Name = D.getIdentifier(); + // Walk the DeclTypeInfo, building the recursive type as we go. // DeclTypeInfos are ordered from the identifier out, which is // opposite of what we want :). @@ -325,72 +539,13 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) { T = Context.getBlockPointerType(T); break; case DeclaratorChunk::Pointer: - if (T->isReferenceType()) { - // C++ 8.3.2p4: There shall be no ... pointers to references ... - Diag(DeclType.Loc, diag::err_illegal_decl_pointer_to_reference) - << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name"); - D.setInvalidType(true); - T = Context.IntTy; - } - - // Enforce C99 6.7.3p2: "Types other than pointer types derived from - // object or incomplete types shall not be restrict-qualified." - if ((DeclType.Ptr.TypeQuals & QualType::Restrict) && - !T->isIncompleteOrObjectType()) { - Diag(DeclType.Loc, diag::err_typecheck_invalid_restrict_invalid_pointee) - << T; - DeclType.Ptr.TypeQuals &= ~QualType::Restrict; - } - - // Apply the pointer typequals to the pointer object. - T = Context.getPointerType(T).getQualifiedType(DeclType.Ptr.TypeQuals); + T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclTyp |