summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp154
1 files changed, 106 insertions, 48 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index cd19d97..70a9270 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -600,7 +600,93 @@ QualType Sema::BuildFunctionType(QualType T,
return Context.getFunctionType(T, ParamTypes, NumParamTypes, Variadic,
Quals);
}
-
+
+/// \brief Build a member pointer type \c T Class::*.
+///
+/// \param T the type to which the member pointer refers.
+/// \param Class the class type into which the member pointer points.
+/// \param Quals Qualifiers applied to the member pointer type
+/// \param Loc the location where this type begins
+/// \param Entity the name of the entity that will have this member pointer type
+///
+/// \returns a member pointer type, if successful, or a NULL type if there was
+/// an error.
+QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
+ unsigned Quals, SourceLocation Loc,
+ DeclarationName Entity) {
+ // Verify that we're not building a pointer to pointer to function with
+ // exception specification.
+ if (CheckDistantExceptionSpec(T)) {
+ Diag(Loc, diag::err_distant_exception_spec);
+
+ // FIXME: If we're doing this as part of template instantiation,
+ // we should return immediately.
+
+ // Build the type anyway, but use the canonical type so that the
+ // exception specifiers are stripped off.
+ T = Context.getCanonicalType(T);
+ }
+
+ // C++ 8.3.3p3: A pointer to member shall not pointer to ... a member
+ // with reference type, or "cv void."
+ if (T->isReferenceType()) {
+ Diag(Loc, diag::err_illegal_decl_pointer_to_reference)
+ << (Entity? Entity.getAsString() : "type name");
+ return QualType();
+ }
+
+ if (T->isVoidType()) {
+ Diag(Loc, diag::err_illegal_decl_mempointer_to_void)
+ << (Entity? Entity.getAsString() : "type name");
+ 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;
+
+ // FIXME: If we're doing this as part of template instantiation,
+ // we should return immediately.
+ Quals &= ~QualType::Restrict;
+ }
+
+ if (!Class->isDependentType() && !Class->isRecordType()) {
+ Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
+ return QualType();
+ }
+
+ return Context.getMemberPointerType(T, Class.getTypePtr())
+ .getQualifiedType(Quals);
+}
+
+/// \brief Build a block pointer type.
+///
+/// \param T The type to which we'll be building a block pointer.
+///
+/// \param Quals 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 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, unsigned Quals,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ if (!T.getTypePtr()->isFunctionType()) {
+ Diag(Loc, diag::err_nonfunction_block_type);
+ return QualType();
+ }
+
+ return Context.getBlockPointerType(T).getQualifiedType(Quals);
+}
+
/// GetTypeForDeclarator - Convert the type for the specified
/// declarator to Type instances. Skip the outermost Skip type
/// objects.
@@ -675,11 +761,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
if (!LangOpts.Blocks)
Diag(DeclType.Loc, diag::err_blocks_disable);
- if (!T.getTypePtr()->isFunctionType())
- Diag(D.getIdentifierLoc(), diag::err_nonfunction_block_type);
- else
- T = (Context.getBlockPointerType(T)
- .getQualifiedType(DeclType.Cls.TypeQuals));
+ T = BuildBlockPointerType(T, DeclType.Cls.TypeQuals, D.getIdentifierLoc(),
+ Name);
break;
case DeclaratorChunk::Pointer:
// Verify that we're not building a pointer to pointer to function with
@@ -870,57 +953,32 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
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.
- DeclContext *DC = computeDeclContext(DeclType.Mem.Scope());
QualType ClsType;
- // FIXME: Extend for dependent types when it's actually supported.
- // See ActOnCXXNestedNameSpecifier.
- if (CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC)) {
+ if (isDependentScopeSpecifier(DeclType.Mem.Scope())) {
+ NestedNameSpecifier *NNS
+ = (NestedNameSpecifier *)DeclType.Mem.Scope().getScopeRep();
+ assert(NNS->getAsType() && "Nested-name-specifier must name a type");
+ ClsType = QualType(NNS->getAsType(), 0);
+ } else if (CXXRecordDecl *RD
+ = dyn_cast_or_null<CXXRecordDecl>(
+ computeDeclContext(DeclType.Mem.Scope()))) {
ClsType = Context.getTagDeclType(RD);
} else {
- if (DC) {
- Diag(DeclType.Mem.Scope().getBeginLoc(),
- diag::err_illegal_decl_mempointer_in_nonclass)
- << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
- << DeclType.Mem.Scope().getRange();
- }
+ Diag(DeclType.Mem.Scope().getBeginLoc(),
+ diag::err_illegal_decl_mempointer_in_nonclass)
+ << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
+ << DeclType.Mem.Scope().getRange();
D.setInvalidType(true);
- ClsType = Context.IntTy;
}
- // C++ 8.3.3p3: A pointer to member shall not pointer to ... a member
- // with reference type, or "cv void."
- if (T->isReferenceType()) {
- Diag(DeclType.Loc, diag::err_illegal_decl_pointer_to_reference)
- << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
- D.setInvalidType(true);
+ if (!ClsType.isNull())
+ T = BuildMemberPointerType(T, ClsType, DeclType.Mem.TypeQuals,
+ DeclType.Loc, D.getIdentifier());
+ if (T.isNull()) {
T = Context.IntTy;
+ D.setInvalidType(true);
}
- if (T->isVoidType()) {
- Diag(DeclType.Loc, diag::err_illegal_decl_mempointer_to_void)
- << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
- 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.Mem.TypeQuals & QualType::Restrict) &&
- !T->isIncompleteOrObjectType()) {
- Diag(DeclType.Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
- << T;
- DeclType.Mem.TypeQuals &= ~QualType::Restrict;
- }
-
- T = Context.getMemberPointerType(T, ClsType.getTypePtr()).
- getQualifiedType(DeclType.Mem.TypeQuals);
-
break;
}
OpenPOWER on IntegriCloud