From 3cc9726a493d90bd8faf094986a59352fd3461cb Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Sun, 31 May 2009 11:47:27 +0000 Subject: [PATCH] Disallow exception specs on typedefs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72664 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 6 ++++-- include/clang/Parse/DeclSpec.h | 8 ++++++++ lib/Parse/DeclSpec.cpp | 2 ++ lib/Parse/ParseDecl.cpp | 11 ++++++++--- lib/Parse/ParseExpr.cpp | 3 ++- lib/Sema/SemaDecl.cpp | 3 ++- lib/Sema/SemaType.cpp | 14 ++++++++------ test/SemaCXX/exception-spec.cpp | 2 +- 8 files changed, 35 insertions(+), 14 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 1f72c24963..732386fa14 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -269,12 +269,14 @@ def err_deleted_decl_not_first : Error< "deleted definition must be first declaration">; // C++ exception specifications +def err_exception_spec_in_typedef : Error< + "exception specifications are not allowed in typedefs">; def err_distant_exception_spec : Error< "exception specifications are not allowed beyond a single level " "of indirection">; def err_incomplete_in_exception_spec : Error< - "%select{|pointer to |member pointer to |reference to }1incomplete type %0 " - "is not allowed in exception specification">; + "%select{|pointer to |reference to }1incomplete type %0 is not allowed " + "in exception specification">; // C++ access checking def err_class_redeclared_with_different_access : Error< diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index 1350c904a2..a0b9b1e7cc 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -559,6 +559,10 @@ struct DeclaratorChunk { /// the function has one. unsigned NumExceptions; + /// ThrowLoc - When hasExceptionSpec is true, the location of the throw + /// keyword introducing the spec. + unsigned ThrowLoc; + /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that /// describe the arguments for this function declarator. This is null if /// there are no arguments specified. @@ -588,6 +592,9 @@ struct DeclaratorChunk { SourceLocation getEllipsisLoc() const { return SourceLocation::getFromRawEncoding(EllipsisLoc); } + SourceLocation getThrowLoc() const { + return SourceLocation::getFromRawEncoding(ThrowLoc); + } }; struct BlockPointerTypeInfo { @@ -704,6 +711,7 @@ struct DeclaratorChunk { SourceLocation EllipsisLoc, ParamInfo *ArgInfo, unsigned NumArgs, unsigned TypeQuals, bool hasExceptionSpec, + SourceLocation ThrowLoc, bool hasAnyExceptionSpec, ActionBase::TypeTy **Exceptions, SourceRange *ExceptionRanges, diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp index f3ff0c6379..d8c6986f9e 100644 --- a/lib/Parse/DeclSpec.cpp +++ b/lib/Parse/DeclSpec.cpp @@ -33,6 +33,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, unsigned NumArgs, unsigned TypeQuals, bool hasExceptionSpec, + SourceLocation ThrowLoc, bool hasAnyExceptionSpec, ActionBase::TypeTy **Exceptions, SourceRange *ExceptionRanges, @@ -50,6 +51,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, I.Fun.NumArgs = NumArgs; I.Fun.ArgInfo = 0; I.Fun.hasExceptionSpec = hasExceptionSpec; + I.Fun.ThrowLoc = ThrowLoc.getRawEncoding(); I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec; I.Fun.NumExceptions = NumExceptions; I.Fun.Exceptions = 0; diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 4fc713c885..39eaf36c95 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2274,6 +2274,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // cv-qualifier-seq[opt]. DeclSpec DS; bool hasExceptionSpec = false; + SourceLocation ThrowLoc; bool hasAnyExceptionSpec = false; llvm::SmallVector Exceptions; llvm::SmallVector ExceptionRanges; @@ -2285,6 +2286,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // Parse exception-specification[opt]. if (Tok.is(tok::kw_throw)) { hasExceptionSpec = true; + ThrowLoc = Tok.getLocation(); ParseExceptionSpecification(Loc, Exceptions, ExceptionRanges, hasAnyExceptionSpec); assert(Exceptions.size() == ExceptionRanges.size() && @@ -2299,7 +2301,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, SourceLocation(), /*arglist*/ 0, 0, DS.getTypeQualifiers(), - hasExceptionSpec, + hasExceptionSpec, ThrowLoc, hasAnyExceptionSpec, Exceptions.data(), ExceptionRanges.data(), @@ -2448,6 +2450,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, DeclSpec DS; bool hasExceptionSpec = false; + SourceLocation ThrowLoc; bool hasAnyExceptionSpec = false; llvm::SmallVector Exceptions; llvm::SmallVector ExceptionRanges; @@ -2460,6 +2463,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // Parse exception-specification[opt]. if (Tok.is(tok::kw_throw)) { hasExceptionSpec = true; + ThrowLoc = Tok.getLocation(); ParseExceptionSpecification(Loc, Exceptions, ExceptionRanges, hasAnyExceptionSpec); assert(Exceptions.size() == ExceptionRanges.size() && @@ -2472,7 +2476,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, EllipsisLoc, ParamInfo.data(), ParamInfo.size(), DS.getTypeQualifiers(), - hasExceptionSpec, + hasExceptionSpec, ThrowLoc, hasAnyExceptionSpec, Exceptions.data(), ExceptionRanges.data(), @@ -2551,7 +2555,8 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, SourceLocation(), &ParamInfo[0], ParamInfo.size(), /*TypeQuals*/0, - /*exception*/false, false, 0, 0, 0, + /*exception*/false, + SourceLocation(), false, 0, 0, 0, LParenLoc, D), RLoc); } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 8b8d4e1924..cd62c64276 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1481,7 +1481,8 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() { ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false, SourceLocation(), 0, 0, 0, - false, false, 0, 0, 0, + false, SourceLocation(), + false, 0, 0, 0, CaretLoc, ParamInfo), CaretLoc); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 09ec071bb1..9c650e61e7 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3164,7 +3164,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, assert(!Error && "Error setting up implicit decl!"); Declarator D(DS, Declarator::BlockContext); D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0, - 0, 0, false, false, 0,0,0, Loc, D), + 0, 0, false, SourceLocation(), + false, 0,0,0, Loc, D), SourceLocation()); D.SetIdentifier(&II, Loc); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 833620b5cf..81ac21123e 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -737,7 +737,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip, // does not have a K&R-style identifier list), then the arguments are part // of the type, otherwise the argument list is (). const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; - + // C99 6.7.5.3p1: The return type may not be a function or array type. if (T->isArrayType() || T->isFunctionType()) { Diag(DeclType.Loc, diag::err_func_returning_array_function) << T; @@ -754,6 +754,12 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip, << Context.getTypeDeclType(Tag); } + // Exception specs are not allowed in typedefs. Complain, but add it + // anyway. + if (FTI.hasExceptionSpec && + 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 @@ -978,17 +984,13 @@ bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) { // C++ 15.4p2: A type denoted in an exception-specification shall not denote // an incomplete type a pointer or reference to an incomplete type, other // than (cv) void*. - // The standard does not mention member pointers, but it has to mean them too. int kind; if (const PointerType* IT = T->getAsPointerType()) { T = IT->getPointeeType(); kind = 1; - } else if (const MemberPointerType* IT = T->getAsMemberPointerType()) { - T = IT->getPointeeType(); - kind = 2; } else if (const ReferenceType* IT = T->getAsReferenceType()) { T = IT->getPointeeType(); - kind = 3; + kind = 2; } else return false; diff --git a/test/SemaCXX/exception-spec.cpp b/test/SemaCXX/exception-spec.cpp index a797dba1d2..ea02aac491 100644 --- a/test/SemaCXX/exception-spec.cpp +++ b/test/SemaCXX/exception-spec.cpp @@ -8,7 +8,7 @@ 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 +typedef int (*pf)() throw(int); // expected-error {{specifications are not allowed in typedefs}} // Some more: // Function returning function with spec -- 2.40.0