Skip to content

Commit 10b9de4

Browse files
author
Sebastian Redl
committed
Disallow exception specifications on multi-level indirections.
llvm-svn: 72571
1 parent 82dbbd7 commit 10b9de4

File tree

4 files changed

+77
-0
lines changed

4 files changed

+77
-0
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,11 @@ def err_deleted_non_function : Error<
268268
def err_deleted_decl_not_first : Error<
269269
"deleted definition must be first declaration">;
270270

271+
// C++ exception specifications
272+
def err_distant_exception_spec : Error<
273+
"exception specifications are not allowed beyond a single level "
274+
"of indirection">;
275+
271276
// C++ access checking
272277
def err_class_redeclared_with_different_access : Error<
273278
"%0 redeclared with '%1' access">;

clang/lib/Sema/Sema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ class Sema : public Action {
349349
QualType GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip = 0,
350350
TagDecl **OwnedDecl = 0);
351351
DeclarationName GetNameForDeclarator(Declarator &D);
352+
bool CheckDistantExceptionSpec(QualType T);
352353

353354
QualType ObjCGetTypeForMethodDefinition(DeclPtrTy D);
354355

clang/lib/Sema/SemaType.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,14 +682,35 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
682682
.getQualifiedType(DeclType.Cls.TypeQuals));
683683
break;
684684
case DeclaratorChunk::Pointer:
685+
// Verify that we're not building a pointer to pointer to function with
686+
// exception specification.
687+
if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
688+
Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
689+
D.setInvalidType(true);
690+
// Build the type anyway.
691+
}
685692
T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name);
686693
break;
687694
case DeclaratorChunk::Reference:
695+
// Verify that we're not building a reference to pointer to function with
696+
// exception specification.
697+
if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
698+
Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
699+
D.setInvalidType(true);
700+
// Build the type anyway.
701+
}
688702
T = BuildReferenceType(T, DeclType.Ref.LValueRef,
689703
DeclType.Ref.HasRestrict ? QualType::Restrict : 0,
690704
DeclType.Loc, Name);
691705
break;
692706
case DeclaratorChunk::Array: {
707+
// Verify that we're not building an array of pointers to function with
708+
// exception specification.
709+
if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
710+
Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
711+
D.setInvalidType(true);
712+
// Build the type anyway.
713+
}
693714
DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
694715
Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
695716
ArrayType::ArraySizeModifier ASM;
@@ -834,6 +855,13 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
834855
break;
835856
}
836857
case DeclaratorChunk::MemberPointer:
858+
// Verify that we're not building a pointer to pointer to function with
859+
// exception specification.
860+
if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
861+
Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
862+
D.setInvalidType(true);
863+
// Build the type anyway.
864+
}
837865
// The scope spec must refer to a class, or be dependent.
838866
DeclContext *DC = computeDeclContext(DeclType.Mem.Scope());
839867
QualType ClsType;
@@ -925,6 +953,24 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
925953
return T;
926954
}
927955

956+
/// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer
957+
/// to member to a function with an exception specification. This means that
958+
/// it is invalid to add another level of indirection.
959+
bool Sema::CheckDistantExceptionSpec(QualType T) {
960+
if (const PointerType *PT = T->getAsPointerType())
961+
T = PT->getPointeeType();
962+
else if (const MemberPointerType *PT = T->getAsMemberPointerType())
963+
T = PT->getPointeeType();
964+
else
965+
return false;
966+
967+
const FunctionProtoType *FnT = T->getAsFunctionProtoType();
968+
if (!FnT)
969+
return false;
970+
971+
return FnT->hasExceptionSpec();
972+
}
973+
928974
/// ObjCGetTypeForMethodDefinition - Builds the type for a method definition
929975
/// declarator
930976
QualType Sema::ObjCGetTypeForMethodDefinition(DeclPtrTy D) {

clang/test/SemaCXX/exception-spec.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: clang-cc -fsyntax-only -verify %s
2+
3+
// Straight from the standard:
4+
// Plain function with spec
5+
void f() throw(int);
6+
// Pointer to function with spec
7+
void (*fp)() throw (int);
8+
// Function taking reference to function with spec
9+
void g(void pfa() throw(int));
10+
// Typedef for pointer to function with spec
11+
typedef int (*pf)() throw(int); // xpected-error spec-on-typedef
12+
13+
// Some more:
14+
// Function returning function with spec
15+
void (*h())() throw(int);
16+
// Ultimate parser thrill: function with spec returning function with spec and
17+
// taking pointer to function with spec.
18+
// The actual function throws int, the return type double, the argument float.
19+
void (*i() throw(int))(void (*)() throw(float)) throw(double);
20+
// Pointer to pointer to function taking function with spec
21+
void (**k)(void pfa() throw(int)); // no-error
22+
// Pointer to pointer to function with spec
23+
void (**j)() throw(int); // expected-error {{not allowed beyond a single}}
24+
// Pointer to function returning pointer to pointer to function with spec
25+
void (**(*h())())() throw(int); // expected-error {{not allowed beyond a single}}

0 commit comments

Comments
 (0)