Skip to content

Commit

Permalink
Disallow exception specifications on multi-level indirections.
Browse files Browse the repository at this point in the history
llvm-svn: 72571
  • Loading branch information
Sebastian Redl committed May 29, 2009
1 parent 82dbbd7 commit 10b9de4
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 0 deletions.
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,11 @@ def err_deleted_non_function : Error<
def err_deleted_decl_not_first : Error<
"deleted definition must be first declaration">;

// C++ exception specifications
def err_distant_exception_spec : Error<
"exception specifications are not allowed beyond a single level "
"of indirection">;

// C++ access checking
def err_class_redeclared_with_different_access : Error<
"%0 redeclared with '%1' access">;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ class Sema : public Action {
QualType GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip = 0,
TagDecl **OwnedDecl = 0);
DeclarationName GetNameForDeclarator(Declarator &D);
bool CheckDistantExceptionSpec(QualType T);

QualType ObjCGetTypeForMethodDefinition(DeclPtrTy D);

Expand Down
46 changes: 46 additions & 0 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,14 +682,35 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
.getQualifiedType(DeclType.Cls.TypeQuals));
break;
case DeclaratorChunk::Pointer:
// 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.
}
T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name);
break;
case DeclaratorChunk::Reference:
// Verify that we're not building a reference 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.
}
T = BuildReferenceType(T, DeclType.Ref.LValueRef,
DeclType.Ref.HasRestrict ? QualType::Restrict : 0,
DeclType.Loc, Name);
break;
case DeclaratorChunk::Array: {
// Verify that we're not building an array of pointers 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.
}
DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
ArrayType::ArraySizeModifier ASM;
Expand Down Expand Up @@ -834,6 +855,13 @@ 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;
Expand Down Expand Up @@ -925,6 +953,24 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
return T;
}

/// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer
/// to member to a function with an exception specification. This means that
/// it is invalid to add another level of indirection.
bool Sema::CheckDistantExceptionSpec(QualType T) {
if (const PointerType *PT = T->getAsPointerType())
T = PT->getPointeeType();
else if (const MemberPointerType *PT = T->getAsMemberPointerType())
T = PT->getPointeeType();
else
return false;

const FunctionProtoType *FnT = T->getAsFunctionProtoType();
if (!FnT)
return false;

return FnT->hasExceptionSpec();
}

/// ObjCGetTypeForMethodDefinition - Builds the type for a method definition
/// declarator
QualType Sema::ObjCGetTypeForMethodDefinition(DeclPtrTy D) {
Expand Down
25 changes: 25 additions & 0 deletions clang/test/SemaCXX/exception-spec.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// RUN: clang-cc -fsyntax-only -verify %s

// Straight from the standard:
// Plain function with spec
void f() throw(int);
// Pointer to function with spec
void (*fp)() throw (int);
// Function taking reference to function with spec
void g(void pfa() throw(int));
// Typedef for pointer to function with spec
typedef int (*pf)() throw(int); // xpected-error spec-on-typedef

// Some more:
// Function returning function with spec
void (*h())() throw(int);
// Ultimate parser thrill: function with spec returning function with spec and
// taking pointer to function with spec.
// The actual function throws int, the return type double, the argument float.
void (*i() throw(int))(void (*)() throw(float)) throw(double);
// Pointer to pointer to function taking function with spec
void (**k)(void pfa() throw(int)); // no-error
// Pointer to pointer to function with spec
void (**j)() throw(int); // expected-error {{not allowed beyond a single}}
// Pointer to function returning pointer to pointer to function with spec
void (**(*h())())() throw(int); // expected-error {{not allowed beyond a single}}

0 comments on commit 10b9de4

Please sign in to comment.