From: Sebastian Redl Date: Sat, 5 Mar 2011 22:42:13 +0000 (+0000) Subject: Propagate new-style exception spec information to Declarator. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6e5d319b671dbb0ecf70619834aa23c853d17621;p=clang Propagate new-style exception spec information to Declarator. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127111 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 1567baaaad..164dac096d 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -1028,11 +1028,8 @@ struct DeclaratorChunk { /// The qualifier bitmask values are the same as in QualType. unsigned TypeQuals : 3; - /// hasExceptionSpec - True if the function has an exception specification. - unsigned hasExceptionSpec : 1; - - /// hasAnyExceptionSpec - True if the function has a throw(...) specifier. - unsigned hasAnyExceptionSpec : 1; + /// ExceptionSpecType - An ExceptionSpecificationType value. + unsigned ExceptionSpecType : 3; /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo. unsigned DeleteArgInfo : 1; @@ -1044,28 +1041,34 @@ struct DeclaratorChunk { /// declarator. unsigned NumArgs; - /// NumExceptions - This is the number of types in the exception-decl, if - /// the function has one. + /// NumExceptions - This is the number of types in the dynamic-exception- + /// decl, if the function has one. unsigned NumExceptions; /// \brief The location of the ref-qualifier, if any. /// /// If this is an invalid location, there is no ref-qualifier. unsigned RefQualifierLoc; - - /// ThrowLoc - When hasExceptionSpec is true, the location of the throw + + /// \brief When ExceptionSpecType isn't EST_None, the location of the /// keyword introducing the spec. - unsigned ThrowLoc; + unsigned ExceptionSpecLoc; /// 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. ParamInfo *ArgInfo; - /// Exceptions - This is a pointer to a new[]'d array of TypeAndRange - /// objects that contain the types in the function's exception - /// specification and their locations. - TypeAndRange *Exceptions; + union { + /// \brief Pointer to a new[]'d array of TypeAndRange objects that + /// contain the types in the function's dynamic exception specification + /// and their locations, if there is one. + TypeAndRange *Exceptions; + + /// \brief Pointer to the expression in the noexcept-specifier of this + /// function, if it has one. + Expr *NoexceptExpr; + }; /// TrailingReturnType - If this isn't null, it's the trailing return type /// specified. This is actually a ParsedType, but stored as void* to @@ -1085,7 +1088,8 @@ struct DeclaratorChunk { void destroy() { if (DeleteArgInfo) delete[] ArgInfo; - delete[] Exceptions; + if (getExceptionSpecType() == EST_Dynamic) + delete[] Exceptions; } /// isKNRPrototype - Return true if this is a K&R style identifier list, @@ -1098,18 +1102,23 @@ struct DeclaratorChunk { SourceLocation getEllipsisLoc() const { return SourceLocation::getFromRawEncoding(EllipsisLoc); } - SourceLocation getThrowLoc() const { - return SourceLocation::getFromRawEncoding(ThrowLoc); + SourceLocation getExceptionSpecLoc() const { + return SourceLocation::getFromRawEncoding(ExceptionSpecLoc); } - + /// \brief Retrieve the location of the ref-qualifier, if any. SourceLocation getRefQualifierLoc() const { return SourceLocation::getFromRawEncoding(RefQualifierLoc); } - + /// \brief Determine whether this function declaration contains a /// ref-qualifier. bool hasRefQualifier() const { return getRefQualifierLoc().isValid(); } + + /// \brief Get the type of exception specification this function has. + ExceptionSpecificationType getExceptionSpecType() const { + return static_cast(ExceptionSpecType); + } }; struct BlockPointerTypeInfo : TypeInfoCommon { @@ -1233,15 +1242,16 @@ struct DeclaratorChunk { unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, - bool hasExceptionSpec, - SourceLocation ThrowLoc, - bool hasAnyExceptionSpec, + ExceptionSpecificationType ESpecType, + SourceLocation ESpecLoc, ParsedType *Exceptions, SourceRange *ExceptionRanges, unsigned NumExceptions, + Expr *NoexceptExpr, SourceLocation LPLoc, SourceLocation RPLoc, Declarator &TheDeclarator, - ParsedType TrailingReturnType = ParsedType()); + ParsedType TrailingReturnType = + ParsedType()); /// getBlockPointer - Return a DeclaratorChunk for a block. /// diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 5cda4e6d5c..7fd49838c8 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3197,13 +3197,12 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, DS.getTypeQualifiers(), RefQualifierIsLValueRef, RefQualifierLoc, - ESpecType == EST_Dynamic || - ESpecType == EST_DynamicAny, - ESpecRange.getBegin(), - ESpecType == EST_DynamicAny, + ESpecType, ESpecRange.getBegin(), DynamicExceptions.data(), DynamicExceptionRanges.data(), DynamicExceptions.size(), + NoexceptExpr.isUsable() ? + NoexceptExpr.get() : 0, LParenLoc, RParenLoc, D, TrailingReturnType), EndLoc); @@ -3453,13 +3452,12 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, DS.getTypeQualifiers(), RefQualifierIsLValueRef, RefQualifierLoc, - ESpecType == EST_Dynamic || - ESpecType == EST_DynamicAny, - ESpecRange.getBegin(), - ESpecType == EST_DynamicAny, + ESpecType, ESpecRange.getBegin(), DynamicExceptions.data(), DynamicExceptionRanges.data(), DynamicExceptions.size(), + NoexceptExpr.isUsable() ? + NoexceptExpr.get() : 0, LParenLoc, RParenLoc, D, TrailingReturnType), EndLoc); @@ -3537,9 +3535,8 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, &ParamInfo[0], ParamInfo.size(), /*TypeQuals*/0, true, SourceLocation(), - /*exception*/false, - SourceLocation(), false, 0, 0, 0, - LParenLoc, RLoc, D), + EST_None, SourceLocation(), 0, 0, + 0, 0, LParenLoc, RLoc, D), RLoc); } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 4a155a302f..ab74d5160d 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1918,8 +1918,9 @@ ExprResult Parser::ParseBlockLiteralExpression() { SourceLocation(), 0, 0, 0, true, SourceLocation(), - false, SourceLocation(), - false, 0, 0, 0, + EST_None, + SourceLocation(), + 0, 0, 0, 0, CaretLoc, CaretLoc, ParamInfo), CaretLoc); diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index df29febe4f..a154fbd79a 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -142,35 +142,36 @@ DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs, unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, - bool hasExceptionSpec, - SourceLocation ThrowLoc, - bool hasAnyExceptionSpec, + ExceptionSpecificationType + ESpecType, + SourceLocation ESpecLoc, ParsedType *Exceptions, SourceRange *ExceptionRanges, unsigned NumExceptions, + Expr *NoexceptExpr, SourceLocation LPLoc, SourceLocation RPLoc, Declarator &TheDeclarator, ParsedType TrailingReturnType) { DeclaratorChunk I; - I.Kind = Function; - I.Loc = LPLoc; - I.EndLoc = RPLoc; - I.Fun.AttrList = attrs.getList(); - I.Fun.hasPrototype = hasProto; - I.Fun.isVariadic = isVariadic; - I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding(); - I.Fun.DeleteArgInfo = false; - I.Fun.TypeQuals = TypeQuals; - I.Fun.NumArgs = NumArgs; - I.Fun.ArgInfo = 0; + I.Kind = Function; + I.Loc = LPLoc; + I.EndLoc = RPLoc; + I.Fun.AttrList = attrs.getList(); + I.Fun.hasPrototype = hasProto; + I.Fun.isVariadic = isVariadic; + I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding(); + I.Fun.DeleteArgInfo = false; + I.Fun.TypeQuals = TypeQuals; + I.Fun.NumArgs = NumArgs; + I.Fun.ArgInfo = 0; I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef; - I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); - I.Fun.hasExceptionSpec = hasExceptionSpec; - I.Fun.ThrowLoc = ThrowLoc.getRawEncoding(); - I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec; - I.Fun.NumExceptions = NumExceptions; - I.Fun.Exceptions = 0; + I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); + I.Fun.ExceptionSpecType = ESpecType; + I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding(); + I.Fun.NumExceptions = 0; + I.Fun.Exceptions = 0; + I.Fun.NoexceptExpr = 0; I.Fun.TrailingReturnType = TrailingReturnType.getAsOpaquePtr(); // new[] an argument array if needed. @@ -190,13 +191,25 @@ DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs, } memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs); } - // new[] an exception array if needed - if (NumExceptions) { - I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; - for (unsigned i = 0; i != NumExceptions; ++i) { - I.Fun.Exceptions[i].Ty = Exceptions[i]; - I.Fun.Exceptions[i].Range = ExceptionRanges[i]; + + // Check what exception specification information we should actually store. + switch (ESpecType) { + default: break; // By default, save nothing. + case EST_Dynamic: + // new[] an exception array if needed + if (NumExceptions) { + I.Fun.NumExceptions = NumExceptions; + I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; + for (unsigned i = 0; i != NumExceptions; ++i) { + I.Fun.Exceptions[i].Ty = Exceptions[i]; + I.Fun.Exceptions[i].Range = ExceptionRanges[i]; + } } + break; + + case EST_ComputedNoexcept: + I.Fun.NoexceptExpr = NoexceptExpr; + break; } return I; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b40d4f3e9e..b674cc1701 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5758,8 +5758,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(), false, false, SourceLocation(), 0, 0, 0, true, SourceLocation(), - false, SourceLocation(), - false, 0,0,0, Loc, Loc, D), + EST_None, SourceLocation(), + 0, 0, 0, 0, Loc, Loc, D), SourceLocation()); D.SetIdentifier(&II, Loc); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index dcd61a8d1a..33df7a0529 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -511,7 +511,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, /*args*/ 0, 0, /*type quals*/ 0, /*ref-qualifier*/true, SourceLocation(), - /*EH*/ false, SourceLocation(), false, 0, 0, 0, + /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0, /*parens*/ loc, loc, declarator)); @@ -1764,9 +1764,9 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // Exception specs are not allowed in typedefs. Complain, but add it // anyway. - if (FTI.hasExceptionSpec && + if (FTI.getExceptionSpecType() != EST_None && D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) - Diag(FTI.getThrowLoc(), diag::err_exception_spec_in_typedef); + Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef); if (!FTI.NumArgs && !FTI.isVariadic && !getLangOptions().CPlusPlus) { // Simple void foo(), where the incoming T is the result type. @@ -1855,9 +1855,11 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } llvm::SmallVector Exceptions; - if (FTI.hasExceptionSpec) { - EPI.HasExceptionSpec = FTI.hasExceptionSpec; - EPI.HasAnyExceptionSpec = FTI.hasAnyExceptionSpec; + if (FTI.getExceptionSpecType() == EST_Dynamic || + FTI.getExceptionSpecType() == EST_DynamicAny) { + EPI.HasExceptionSpec = true; + EPI.HasAnyExceptionSpec = + FTI.getExceptionSpecType() == EST_DynamicAny; Exceptions.reserve(FTI.NumExceptions); for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) { // FIXME: Preserve type source info.