Propagate new-style exception spec information to Declarator.

llvm-svn: 127111
This commit is contained in:
Sebastian Redl 2011-03-05 22:42:13 +00:00
parent 75e7a147ae
commit 802a45332a
6 changed files with 93 additions and 70 deletions

View File

@ -1028,11 +1028,8 @@ struct DeclaratorChunk {
/// The qualifier bitmask values are the same as in QualType. /// The qualifier bitmask values are the same as in QualType.
unsigned TypeQuals : 3; unsigned TypeQuals : 3;
/// hasExceptionSpec - True if the function has an exception specification. /// ExceptionSpecType - An ExceptionSpecificationType value.
unsigned hasExceptionSpec : 1; unsigned ExceptionSpecType : 3;
/// hasAnyExceptionSpec - True if the function has a throw(...) specifier.
unsigned hasAnyExceptionSpec : 1;
/// DeleteArgInfo - If this is true, we need to delete[] ArgInfo. /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo.
unsigned DeleteArgInfo : 1; unsigned DeleteArgInfo : 1;
@ -1044,28 +1041,34 @@ struct DeclaratorChunk {
/// declarator. /// declarator.
unsigned NumArgs; unsigned NumArgs;
/// NumExceptions - This is the number of types in the exception-decl, if /// NumExceptions - This is the number of types in the dynamic-exception-
/// the function has one. /// decl, if the function has one.
unsigned NumExceptions; unsigned NumExceptions;
/// \brief The location of the ref-qualifier, if any. /// \brief The location of the ref-qualifier, if any.
/// ///
/// If this is an invalid location, there is no ref-qualifier. /// If this is an invalid location, there is no ref-qualifier.
unsigned RefQualifierLoc; 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. /// keyword introducing the spec.
unsigned ThrowLoc; unsigned ExceptionSpecLoc;
/// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that /// 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 /// describe the arguments for this function declarator. This is null if
/// there are no arguments specified. /// there are no arguments specified.
ParamInfo *ArgInfo; ParamInfo *ArgInfo;
/// Exceptions - This is a pointer to a new[]'d array of TypeAndRange union {
/// objects that contain the types in the function's exception /// \brief Pointer to a new[]'d array of TypeAndRange objects that
/// specification and their locations. /// contain the types in the function's dynamic exception specification
TypeAndRange *Exceptions; /// 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 /// TrailingReturnType - If this isn't null, it's the trailing return type
/// specified. This is actually a ParsedType, but stored as void* to /// specified. This is actually a ParsedType, but stored as void* to
@ -1085,7 +1088,8 @@ struct DeclaratorChunk {
void destroy() { void destroy() {
if (DeleteArgInfo) if (DeleteArgInfo)
delete[] ArgInfo; delete[] ArgInfo;
delete[] Exceptions; if (getExceptionSpecType() == EST_Dynamic)
delete[] Exceptions;
} }
/// isKNRPrototype - Return true if this is a K&R style identifier list, /// isKNRPrototype - Return true if this is a K&R style identifier list,
@ -1098,18 +1102,23 @@ struct DeclaratorChunk {
SourceLocation getEllipsisLoc() const { SourceLocation getEllipsisLoc() const {
return SourceLocation::getFromRawEncoding(EllipsisLoc); return SourceLocation::getFromRawEncoding(EllipsisLoc);
} }
SourceLocation getThrowLoc() const { SourceLocation getExceptionSpecLoc() const {
return SourceLocation::getFromRawEncoding(ThrowLoc); return SourceLocation::getFromRawEncoding(ExceptionSpecLoc);
} }
/// \brief Retrieve the location of the ref-qualifier, if any. /// \brief Retrieve the location of the ref-qualifier, if any.
SourceLocation getRefQualifierLoc() const { SourceLocation getRefQualifierLoc() const {
return SourceLocation::getFromRawEncoding(RefQualifierLoc); return SourceLocation::getFromRawEncoding(RefQualifierLoc);
} }
/// \brief Determine whether this function declaration contains a /// \brief Determine whether this function declaration contains a
/// ref-qualifier. /// ref-qualifier.
bool hasRefQualifier() const { return getRefQualifierLoc().isValid(); } bool hasRefQualifier() const { return getRefQualifierLoc().isValid(); }
/// \brief Get the type of exception specification this function has.
ExceptionSpecificationType getExceptionSpecType() const {
return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
}
}; };
struct BlockPointerTypeInfo : TypeInfoCommon { struct BlockPointerTypeInfo : TypeInfoCommon {
@ -1233,15 +1242,16 @@ struct DeclaratorChunk {
unsigned TypeQuals, unsigned TypeQuals,
bool RefQualifierIsLvalueRef, bool RefQualifierIsLvalueRef,
SourceLocation RefQualifierLoc, SourceLocation RefQualifierLoc,
bool hasExceptionSpec, ExceptionSpecificationType ESpecType,
SourceLocation ThrowLoc, SourceLocation ESpecLoc,
bool hasAnyExceptionSpec,
ParsedType *Exceptions, ParsedType *Exceptions,
SourceRange *ExceptionRanges, SourceRange *ExceptionRanges,
unsigned NumExceptions, unsigned NumExceptions,
Expr *NoexceptExpr,
SourceLocation LPLoc, SourceLocation RPLoc, SourceLocation LPLoc, SourceLocation RPLoc,
Declarator &TheDeclarator, Declarator &TheDeclarator,
ParsedType TrailingReturnType = ParsedType()); ParsedType TrailingReturnType =
ParsedType());
/// getBlockPointer - Return a DeclaratorChunk for a block. /// getBlockPointer - Return a DeclaratorChunk for a block.
/// ///

View File

@ -3197,13 +3197,12 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
DS.getTypeQualifiers(), DS.getTypeQualifiers(),
RefQualifierIsLValueRef, RefQualifierIsLValueRef,
RefQualifierLoc, RefQualifierLoc,
ESpecType == EST_Dynamic || ESpecType, ESpecRange.getBegin(),
ESpecType == EST_DynamicAny,
ESpecRange.getBegin(),
ESpecType == EST_DynamicAny,
DynamicExceptions.data(), DynamicExceptions.data(),
DynamicExceptionRanges.data(), DynamicExceptionRanges.data(),
DynamicExceptions.size(), DynamicExceptions.size(),
NoexceptExpr.isUsable() ?
NoexceptExpr.get() : 0,
LParenLoc, RParenLoc, D, LParenLoc, RParenLoc, D,
TrailingReturnType), TrailingReturnType),
EndLoc); EndLoc);
@ -3453,13 +3452,12 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
DS.getTypeQualifiers(), DS.getTypeQualifiers(),
RefQualifierIsLValueRef, RefQualifierIsLValueRef,
RefQualifierLoc, RefQualifierLoc,
ESpecType == EST_Dynamic || ESpecType, ESpecRange.getBegin(),
ESpecType == EST_DynamicAny,
ESpecRange.getBegin(),
ESpecType == EST_DynamicAny,
DynamicExceptions.data(), DynamicExceptions.data(),
DynamicExceptionRanges.data(), DynamicExceptionRanges.data(),
DynamicExceptions.size(), DynamicExceptions.size(),
NoexceptExpr.isUsable() ?
NoexceptExpr.get() : 0,
LParenLoc, RParenLoc, D, LParenLoc, RParenLoc, D,
TrailingReturnType), TrailingReturnType),
EndLoc); EndLoc);
@ -3537,9 +3535,8 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
&ParamInfo[0], ParamInfo.size(), &ParamInfo[0], ParamInfo.size(),
/*TypeQuals*/0, /*TypeQuals*/0,
true, SourceLocation(), true, SourceLocation(),
/*exception*/false, EST_None, SourceLocation(), 0, 0,
SourceLocation(), false, 0, 0, 0, 0, 0, LParenLoc, RLoc, D),
LParenLoc, RLoc, D),
RLoc); RLoc);
} }

View File

@ -1918,8 +1918,9 @@ ExprResult Parser::ParseBlockLiteralExpression() {
SourceLocation(), SourceLocation(),
0, 0, 0, 0, 0, 0,
true, SourceLocation(), true, SourceLocation(),
false, SourceLocation(), EST_None,
false, 0, 0, 0, SourceLocation(),
0, 0, 0, 0,
CaretLoc, CaretLoc, CaretLoc, CaretLoc,
ParamInfo), ParamInfo),
CaretLoc); CaretLoc);

View File

@ -142,35 +142,36 @@ DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs,
unsigned TypeQuals, unsigned TypeQuals,
bool RefQualifierIsLvalueRef, bool RefQualifierIsLvalueRef,
SourceLocation RefQualifierLoc, SourceLocation RefQualifierLoc,
bool hasExceptionSpec, ExceptionSpecificationType
SourceLocation ThrowLoc, ESpecType,
bool hasAnyExceptionSpec, SourceLocation ESpecLoc,
ParsedType *Exceptions, ParsedType *Exceptions,
SourceRange *ExceptionRanges, SourceRange *ExceptionRanges,
unsigned NumExceptions, unsigned NumExceptions,
Expr *NoexceptExpr,
SourceLocation LPLoc, SourceLocation LPLoc,
SourceLocation RPLoc, SourceLocation RPLoc,
Declarator &TheDeclarator, Declarator &TheDeclarator,
ParsedType TrailingReturnType) { ParsedType TrailingReturnType) {
DeclaratorChunk I; DeclaratorChunk I;
I.Kind = Function; I.Kind = Function;
I.Loc = LPLoc; I.Loc = LPLoc;
I.EndLoc = RPLoc; I.EndLoc = RPLoc;
I.Fun.AttrList = attrs.getList(); I.Fun.AttrList = attrs.getList();
I.Fun.hasPrototype = hasProto; I.Fun.hasPrototype = hasProto;
I.Fun.isVariadic = isVariadic; I.Fun.isVariadic = isVariadic;
I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding(); I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
I.Fun.DeleteArgInfo = false; I.Fun.DeleteArgInfo = false;
I.Fun.TypeQuals = TypeQuals; I.Fun.TypeQuals = TypeQuals;
I.Fun.NumArgs = NumArgs; I.Fun.NumArgs = NumArgs;
I.Fun.ArgInfo = 0; I.Fun.ArgInfo = 0;
I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef; I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef;
I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
I.Fun.hasExceptionSpec = hasExceptionSpec; I.Fun.ExceptionSpecType = ESpecType;
I.Fun.ThrowLoc = ThrowLoc.getRawEncoding(); I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding();
I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec; I.Fun.NumExceptions = 0;
I.Fun.NumExceptions = NumExceptions; I.Fun.Exceptions = 0;
I.Fun.Exceptions = 0; I.Fun.NoexceptExpr = 0;
I.Fun.TrailingReturnType = TrailingReturnType.getAsOpaquePtr(); I.Fun.TrailingReturnType = TrailingReturnType.getAsOpaquePtr();
// new[] an argument array if needed. // 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); memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
} }
// new[] an exception array if needed
if (NumExceptions) { // Check what exception specification information we should actually store.
I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; switch (ESpecType) {
for (unsigned i = 0; i != NumExceptions; ++i) { default: break; // By default, save nothing.
I.Fun.Exceptions[i].Ty = Exceptions[i]; case EST_Dynamic:
I.Fun.Exceptions[i].Range = ExceptionRanges[i]; // 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; return I;
} }

View File

@ -5758,8 +5758,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(), D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(),
false, false, SourceLocation(), 0, false, false, SourceLocation(), 0,
0, 0, true, SourceLocation(), 0, 0, true, SourceLocation(),
false, SourceLocation(), EST_None, SourceLocation(),
false, 0,0,0, Loc, Loc, D), 0, 0, 0, 0, Loc, Loc, D),
SourceLocation()); SourceLocation());
D.SetIdentifier(&II, Loc); D.SetIdentifier(&II, Loc);

View File

@ -511,7 +511,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
/*args*/ 0, 0, /*args*/ 0, 0,
/*type quals*/ 0, /*type quals*/ 0,
/*ref-qualifier*/true, SourceLocation(), /*ref-qualifier*/true, SourceLocation(),
/*EH*/ false, SourceLocation(), false, 0, 0, 0, /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0,
/*parens*/ loc, loc, /*parens*/ loc, loc,
declarator)); declarator));
@ -1764,9 +1764,9 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// Exception specs are not allowed in typedefs. Complain, but add it // Exception specs are not allowed in typedefs. Complain, but add it
// anyway. // anyway.
if (FTI.hasExceptionSpec && if (FTI.getExceptionSpecType() != EST_None &&
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) 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) { if (!FTI.NumArgs && !FTI.isVariadic && !getLangOptions().CPlusPlus) {
// Simple void foo(), where the incoming T is the result type. // Simple void foo(), where the incoming T is the result type.
@ -1855,9 +1855,11 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
} }
llvm::SmallVector<QualType, 4> Exceptions; llvm::SmallVector<QualType, 4> Exceptions;
if (FTI.hasExceptionSpec) { if (FTI.getExceptionSpecType() == EST_Dynamic ||
EPI.HasExceptionSpec = FTI.hasExceptionSpec; FTI.getExceptionSpecType() == EST_DynamicAny) {
EPI.HasAnyExceptionSpec = FTI.hasAnyExceptionSpec; EPI.HasExceptionSpec = true;
EPI.HasAnyExceptionSpec =
FTI.getExceptionSpecType() == EST_DynamicAny;
Exceptions.reserve(FTI.NumExceptions); Exceptions.reserve(FTI.NumExceptions);
for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) { for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) {
// FIXME: Preserve type source info. // FIXME: Preserve type source info.